Hash 为什么5381和33在djb2算法中如此重要?

Hash 为什么5381和33在djb2算法中如此重要?,hash,Hash,具有字符串的哈希函数 unsigned long hash = 5381; int c; while (c = *str++) hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 无符号长哈希=5381; INTC; 而(c=*str++) hash=((hash可能是因为33==2^5+1和许多哈希算法使用2^n+1作为它们的乘数 归功于 更新: 这似乎可以从软件包djb2的当前版本得到证实,该软件包最初来自: 我链

具有字符串的哈希函数

unsigned long hash = 5381;
int c;

while (c = *str++)
    hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
无符号长哈希=5381;
INTC;
而(c=*str++)

hash=((hash可能是因为
33==2^5+1
和许多哈希算法使用
2^n+1
作为它们的乘数

归功于

更新:

这似乎可以从软件包djb2的当前版本得到证实,该软件包最初来自:

我链接的注释描述了散列算法的核心是使用
h=((h在5381上,Dan Bernstein(djb2)在:

[…]几乎任何好的乘数都能起作用。我想你在担心 关于31c+d不包括任何合理的散列范围这一事实 如果c和d介于0和255之间,则值。这就是为什么,当我发现 33散列函数并开始在我的压缩器中使用它,我开始 散列值为5381。我想你会发现这和 以及261乘数。 如果你感兴趣的话,整个主题就是

Ozan Yigit说:

[…]数字33的魔力(为什么它比许多其他常数,素数与否,都更有效)从未得到充分解释。
该散列函数类似于(LCG-生成一系列psuedo随机数的简单函数类),通常具有以下形式:

X = (a * X) + c;  // "mod M", where M = 2^32 or 2^64 typically
请注意与djb2哈希函数的相似性…a=33,M=2^32。为了使LCG具有“完整周期”(即尽可能随机),a必须具有某些属性:

  • a-1可被M的所有素数因子整除(a-1为32,可被2整除,2^32的唯一素数因子)
  • 如果M是4的倍数(是和是),则a-1是4的倍数
此外,c和M被认为是相对素数(对于c的奇数值也是如此)

正如你所看到的,这个散列函数有点像一个好的LCG。当涉及到散列函数时,你需要一个在给定一组真实的输入字符串的情况下产生散列值“随机”分布的函数

至于为什么这个散列函数适合字符串,我认为它有一个很好的平衡,即速度非常快,同时提供了合理的散列值分布。但我见过许多其他散列函数,它们声称具有更好的输出特性,但涉及更多的代码行。例如

编辑:解释为什么选择33和5381是出于实际原因。

33是因为:

1) 如前所述,使用移位和加法很容易计算乘法

(二)从shift和add实现中可以看到,使用33将散列累加器中的大部分输入位复制两个副本,然后将这些位分散相对较远。这有助于产生良好的Avalanch。使用较大的移位将复制较少的位,使用较小的移位将使位交互更局部,并使其耗时互动传播的时间更长

3) 5的移位相对于32(寄存器中的位数)而言是最基本的,这有助于保证。虽然字符串中还有足够的字符,但输入字节的每一位最终都会与输入的前一位交互

4) 在考虑ASCII字符数据时,移位5是一个很好的移位量。ASCII字符可以被看作是4位字符类型选择器和4位字符类型选择器。例如,所有数字的前4位都有0x3。因此,8位移位将导致具有特定含义的位主要与具有相同含义的其他位交互。4位或2位移位同样会在志同道合的位之间产生强烈的交互作用。5位移位会导致一个字符的四个低位中的许多位与同一字符中的多个高位强烈交互

如其他地方所述,5381的选择并不太重要,许多其他选择在这里也应该起作用

这不是一个快速散列函数,因为它一次处理输入的字符,并且不尝试使用指令级并行。然而,它很容易写。输出的质量除以编写代码的难易程度很可能达到最佳值

在现代处理器上,乘法运算比开发此算法时快得多,其他乘法因子(例如2^13+2^5+1)可能具有类似的性能,输出稍好,编写也稍容易


与上面的答案相反,好的非加密散列函数不希望产生随机输出。相反,考虑到两个几乎相同的输入,它希望产生完全不同的输出。如果输入值是随机分布的,则不需要好的哈希函数,只需使用输入中的任意一组位即可。一些现代散列函数(Jenkins 3,Murrul,可能是CityHash)比高度相似的随机给定输入产生更好的输出分布。

请注意,散列的起始值(5381)对于长度相等的字符串没有区别,但是将在为不同长度的字符串生成不同的哈希值方面发挥作用。这个答案实际上回答了这个问题。谢谢然而,DJB2的可能复制品在雪崩中是不好的。例如,它为这些字符串返回相同的哈希:
xy
yX
z7
。有。