djb2 algorithm有一个用于字符串的散列函数。
unsigned long hash = 5381;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
为什么5381和33如此重要?
发布于 2015-07-25 07:37:16
选择33是因为:
1)如前所述,使用移位和加法很容易计算乘法。
2)正如您从shift和add实现中看到的,使用33将散列累加器中的大部分输入位复制为两个副本,然后将这些位分散到相对较远的位置。这有助于产生良好的雪崩。使用较大的移位将复制较少的比特,使用较小的移位将使比特交互更具局部性,并使交互传播的时间更长。
3) 5的移位相对质数为32 (寄存器中的位数),这有助于雪崩。虽然字符串中还有足够的字符,但输入字节的每一位最终都会与前面的每一位输入进行交互。
4)在考虑ASCII字符数据时,5的移位量是一个很好的移位量。ASCII字符可以看作是一个4位字符类型选择器和一个4位字符类型选择器。例如,所有数字的前4位都有0x3。因此,8位移位将导致具有特定含义的位主要与具有相同含义的其他位交互。4位或2位移位同样会在志同道合的位之间产生强烈的交互作用。5位移位导致字符的四个低位中的许多位与同一字符中的许多四位高位强烈交互。
正如前面所说的,5381的选择并不太重要,许多其他的选择在这里应该也可以。
这不是一个快速的哈希函数,因为它一次处理一个字符的输入,并且不会尝试使用指令级并行。然而,它很容易编写。输出的质量除以编写代码的容易程度可能会达到最佳点。
在现代处理器上,乘法比开发此算法时快得多,其他乘法因子(例如2^13 + 2^5 + 1)可能具有类似的性能,输出略好,并且更易于编写。
与上面的答案相反,一个好的非加密散列函数不想产生随机输出。相反,给定两个几乎相同的输入,它希望产生完全不同的输出。如果你的输入值是随机分布的,你不需要一个好的哈希函数,你可以只使用输入中的任意一组位。一些现代散列函数(Jenkins 3,Murmur,可能是CityHash)比高度相似的随机给定输入产生更好的输出分布。
https://stackoverflow.com/questions/1579721
复制相似问题