DJB哈希函数中数字5381的原因是什么?

63

请问为什么在DJB哈希函数中使用数字5381?

DJB哈希函数定义如下:

  • h 0 = 5381

  • h i = 33h i - 1 + s i

以下是C语言实现代码:

unsigned int DJBHash(char* str, unsigned int len)
{
   unsigned int hash = 5381;
   unsigned int i    = 0;

   for(i = 0; i < len; str++, i++)
   {   
      hash = ((hash << 5) + hash) + (*str);
   }   

   return hash;
}

这是一个相对较大的质数,在大多数哈希算法中用作乘数,以分散值。 - user207421
3个回答

84
我发现一个comment,阐明了DJB在做什么:
/*
* DJBX33A (Daniel J. Bernstein, Times 33 with Addition)
*
* This is Daniel J. Bernstein's popular `times 33' hash function as
* posted by him years ago on comp.lang.c. It basically uses a function
* like ``hash(i) = hash(i-1) * 33 + str[i]''. This is one of the best
* known hash functions for strings. Because it is both computed very
* fast and distributes very well.
*
* The magic of number 33, i.e. why it works better than many other
* constants, prime or not, has never been adequately explained by
* anyone. So I try an explanation: if one experimentally tests all
* multipliers between 1 and 256 (as RSE did now) one detects that even
* numbers are not useable at all. The remaining 128 odd numbers
* (except for the number 1) work more or less all equally well. They
* all distribute in an acceptable way and this way fill a hash table
* with an average percent of approx. 86%.
*
* If one compares the Chi^2 values of the variants, the number 33 not
* even has the best value. But the number 33 and a few other equally
* good numbers like 17, 31, 63, 127 and 129 have nevertheless a great
* advantage to the remaining numbers in the large set of possible
* multipliers: their multiply operation can be replaced by a faster
* operation based on just one shift plus either a single addition
* or subtraction operation. And because a hash function has to both
* distribute good _and_ has to be very fast to compute, those few
* numbers should be preferred and seems to be the reason why Daniel J.
* Bernstein also preferred it.
*
*
* -- Ralf S. Engelschall <rse@engelschall.com>
*/

这是一个略微不同的哈希函数,虽然它确实使用了5381这个魔法数字。在链接目标处的注释下面的代码已经展开。

然后我找到了this

Magic Constant 5381:

  1. odd number

  2. prime number

  3. deficient number

  4. 001/010/100/000/101 b

这里还有一个this关于能否解释一下djb2哈希函数背后的逻辑?的答案,它引用了DJB本人在邮件列表中的post,其中提到了5381(以下是该答案的摘录):

[...] 实际上,任何好的乘数都可以。我认为你担心的是,如果c和d在0到255之间,31c + d无法涵盖任何合理范围的哈希值。这就是为什么当我发现33哈希函数并开始在我的压缩程序中使用它时,我从哈希值5381开始。我认为你会发现,这与261个乘数一样好。


谢谢 - 最后一条评论正中了5381的要害。 - PlanetUnknown
它们不是“稍有不同”。(x << 5) + x是按位乘法。它等同于x * 33!在某些系统上,使用按位方法更快,或者是执行乘法的唯一方法。 - bryc

38

3
那些交换过的网址让我笑了。 - High Performance Mark
@High,我很高兴你心情不错 :) 幸运的是,交换URL非常容易,我只需要把数字换一下就可以了。 - Mahmoud Al-Qudsi
我无法理解上面的幽默。 - Suraj Jain
2
问题是它如何减少碰撞的?我也大声笑了起来。此外,提问者竟然在没有任何证据的情况下接受了答案!!! - AnotherDeveloper
3
djb2(类似于fnv1a)实际上具有不良的雪崩/分布。它们甚至无法满足非严格雪崩准则,这需要更少的计算能力来计算。但是它们确实具有相当不错的碰撞率。:)通常,碰撞率与其雪崩行为有关,这意味着djb2并不像其他选择那样好。越接近所有位数都是伪随机的,任何两个值匹配的可能性就越小。 - bryc

34

我发现这个数字有一个非常有趣的特性,也许这就是原因。

5381是第709个质数。
709是第127个质数。
127是第31个质数。
31是第11个质数。
11是第5个质数。
5是第3个质数。
3是第2个质数。
2是第1个质数。

5381是第一个在其中连续出现8次的数字。第5381个质数可能超过signed int的限制,所以这是停止连锁的好时机。


5
第5381个质数距离有符号整数的极限还有很大的距离。 - evil otto
1
@evilotto 在这段代码中,他使用了无符号整数,它可以存储值52711。 - Deep Joshi
1
@JakubKaszycki 我在休闲数学中找到了它。 - Deep Joshi
1
这是在线整数序列百科全书中的序列A007097 - Craig McQueen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接