我正在尝试在基于
PHP的项目上集成
FNV哈希算法,作为为各种数据(例如URL,关键字)生成哈希的要求的一部分.
我在Neven Boyanov看到了这个implementation.他提到由于PHP中的算术限制,他被迫使用按位移位和加法而不是乘法.他的实施是否正确?我的知识在某种程度上受限于计算机科学领域,所以我无法自己验证.
我的另一个问题是关于FNV的不同’风味’.我看到它提供了32位,64位和128位变体,但是使用上面的实现我总是得到8个字符的十六进制哈希(我使用dechex()将整数结果转换为十六进制).
鉴于输入“Lorem ipsum dolor sit amet,consectetur adipiscing elit.Proin at libero mi,quis luctus massa.”,我得到以下十六进制结果:
>(32位偏移)5b15c0f2
>(64位偏移)6ea33cb5
为什么会这样?我期待64位FNV的16个字符的十六进制结果. “风味”是指仅使用的算术运算种子和种子而不是结果的长度吗? (即如果我说64位FNV,散列函数将使用64位操作和种子,但结果仍然是32位)
一点启示将非常感激:)
最佳答案 我很久以前就编写了PHP FNV哈希函数,这是出于特定目的,所以当时32位实现就足够了.
回答第一个问题 – 通过比较算法(代码)和样本结果,对其他(C和C)实现进行了测试.因此,对于32位结果,它可以正常工作.
如果你想自己实现64位(或128位)版本,你应该先改变FNV_offset_basis,还要改变第73行的表达式,它当前是:
$hash += ($hash<<1) + ($hash<<4) + ($hash<<7) + ($hash<<8) + ($hash<<24);
…相当于乘以数字16777619(FNV_prime_32),二进制数为1000000000000000110010011 – 细分为此表达式:2 ^ 24 2 ^ 8 2 ^ 7 2 ^ 4 2 ^ 1 2 ^ 0.
对于64位,您应该乘以1099511628211 – 二进制10000000000000000000000000000000110110011 …表达式:2 ^ 88 2 ^ 8 2 ^ 7 2 ^ 5 2 ^ 4 2 ^ 1 2 ^ 0.
我不知道表达式如何$hash<< 88将由PHP处理,但你应该自己试验.在我的PHP 5.2.x上,它对于大于31的数字不适用. 最后,您可能需要修改$hash = $hash& 0x0ffffffff;从结果中删除一些垃圾.我通过实验想出来了.对于64位ot应该像$hash = $hash& 0x0ffffffffffffffff ;.验证它是否与PHP一起正常工作. 您还可以使用其他PHP库来获得更高的算术精度.在我看来,使用按位移位更快. 实际上,您可以为任意数量的位生成FNV Hash.