什么整数散列函数是好的,接受一个整数散列键?

什么整数散列函数是好的,接受一个整数散列键?

Knuth的乘法方法:

hash(i)=i*2654435761 mod 2^32 

一般来说,你应该select一个乘以你的哈希大小的顺序(在这个例子中是2^32 ),并没有共同的因素。 这样散列函数统一覆盖了所有的散列空间。

编辑:这个哈希函数的最大的缺点是它保留可分性,所以如果你的整数都是2或4(这并不less见),它们的哈希值也是可以被整除的。 这在散列表中是一个问题 – 最终只能使用1/2或1/4的桶。

我发现下面的algorithm提供了非常好的统计分布。 每个input位以约50%的概率影响每个输出位。 没有碰撞(每个input导致不同的输出)。 除非CPU没有内置的整数乘法单元,否则algorithm很快。 C代码,假设int是32位(对于Java,用>>>replace>>并删除unsigned ):

 unsigned int hash(unsigned int x) { x = ((x >> 16) ^ x) * 0x45d9f3b; x = ((x >> 16) ^ x) * 0x45d9f3b; x = (x >> 16) ^ x; return x; } 

这个幻数是用一个特殊的multithreadingtesting程序计算出来的,这个testing程序运行了好几个小时,计算了雪崩效应(如果一个input比特被改变,输出比特数就会变化;平均应该接近16)输出位变化(输出位不应相互依赖)以及每个输出位发生变化的概率。 所计算的值比MurmurHash使用的32位终结器更好,并且与使用AES时几乎一样好(不完全)。

对于64位数字,我build议使用以下,甚至认为它可能不是最快的。 这是基于splitmix64 ,这似乎是基于博客文章Better Bit Mixing (混合13):

 uint64_t hash(uint64_t x) { x = (x ^ (x >> 30)) * UINT64_C(0xbf58476d1ce4e5b9); x = (x ^ (x >> 27)) * UINT64_C(0x94d049bb133111eb); x = x ^ (x >> 31); return x; } 

(对于Java,使用long ,向常量添加L ,用>>>replace>>并删除unsigned

取决于你的数据如何分配。 对于一个简单的计数器,最简单的function

 f(i) = i 

将是好的(我怀疑是最佳的,但我不能certificate这一点)。

这个页面列出了一些简单的散列函数,但总体而言,它们可以体现得很好,但是任何简单的散列函数都有病态的情况。

  • 32位乘法(非常快)见@rafal

     #define hash32(x) ((x)*2654435761) #define H_BITS 24 // Hashtable size #define H_SHIFT (32-H_BITS) unsigned hashtab[1<<H_BITS] .... unsigned slot = hash32(x) >> H_SHIFT 
  • 32位和64位(良好分布): MurmurHash

  • 整数散列函数

Eternal Confuzzled上的一些散列algorithm有一个很好的概述。 我build议Bob Jenkins一次一个的散列快速到达雪崩,因此可以用于高效的散列表查找。

答案取决于很多事情,如:

  • 你打算雇用它在哪里?
  • 你想用散列做什么?
  • 你需要一个crytographically安全的哈希函数?

我build议你看看像SHA-1等散列函数的Merkle-Damgard系列


感谢mmeyers! 出于某种原因,这几天以来,我:

  • 无法阅读后评论
  • 不能正确使用超链接
  • 我不得不为每一个职位使用CAPTCHA

我不认为我们可以说没有提前知道您的数据哈希函数是“好”! 而不知道你将要用它做什么。

对于未知的数据大小,有比散列表更好的数据结构(我假设你正在这里做一个散列表的散列表)。 当我知道我有一个“有限”数量的元素需要存储在有限的内存中时,我会亲自使用一个哈希表。 我会尝试做一个快速的统计分析我的数据,看看它是如何分布等开始思考我的散列函数。