如果我使用64位无符号整数,Dan Bernstein的哈希函数是否仍能正常运行?
uint64
hash_djb2(register uchar *str, register size_t length) {
register uint64 hash = 5381L;
while (length--) {
hash = ((hash << 5L) + hash) + *str++; /* hash * 33 + c */
}
return hash;
}
答案 0 :(得分:8)
djb哈希函数基于Linear Congruential Generator,其形式为x =(a·x + c)mod m。
通过检查函数,我们在djb的情况下意识到a = 33
,c = input
但模数有点隐藏,因为它是由变量哈希的类型声明的, unsigned long ,原始形式,包含32位数据。当值超出无符号长整数的值时,它会溢出并继续,因此模数为2 ^ 32。
根据Knuth在他的“计算机程序设计的艺术”第2卷:第3.2.1章的数值算法中,m必须能够被(a-1)的所有素因子整除,以使线性同余生成器具有最大周期( period = modulo)(以及Bernstein先生已经考虑过的其他事实)。由于m = 2^64
没有引入新的素因子,因此根据定义2
是2^32
和2^64
的素数,因此满足此规则。
然后,使用这种新的哈希算法,您可以获得与模数一样长的句点,这意味着您将覆盖64位整数的所有可能值。
请记住,虽然改变算法的任何数学值都不能轻易做到。需要一个全新的统计分析来充分了解新算法的缺陷和好处,即使您只更改了它的一个变量。您不能简单地更改值,并希望获得与原始线性同余生成器相同的功能。前一算法不保留熵和碰撞等统计特征。然后你不能声称已经实现了djb算法,既不引用djb的任何统计性能来证明你的实现有什么。
答案 1 :(得分:2)
我不知道所有2 ^ 64个可能值的分布是否与32位版本相同,但仍有一个重要属性。乘数33
不与2 ^ 64共享任何公约数。因此,通过散列运行的所有字符仍将对最终结果产生影响。换句话说,这两个字符串的哈希结果将是不同的:
hash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") => 0x87b2af4e3d92de7a
hash("baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") => 0xd496edbee1219cfb
它应该仍然是一个有用的哈希函数。当然,我不禁想知道为什么你需要这么大的哈希值。一个非常大的哈希表?还是其他一些用途?