1 function Fingerprint($str) { 2 $kFingerPrintSeed = 19820125; 3 return MurmurHash64A($str, $kFingerPrintSeed); 4 } 5 6 function getBytes($str) { 7 $len = strlen($str); 8 $bytes = array(); 9 for($i=0;$i<$len;$i++) { 10 $bytes[] = ord($str[$i]); 11 } 12 return $bytes; 13 } 14 15 function multi64($x, $y) { 16 $result = 0; 17 for($i = 0; $i < 64; $i++) { 18 $bit = ($x >> $i) & 1; 19 if($bit) { 20 $result = add64($result, $y << $i); 21 } 22 } 23 return $result; 24 } 25 26 function r_shift($num, $bit) { 27 if($bit <= 0) return $num; 28 if($num > 0) { 29 return $num>>$bit; 30 } else { 31 $num = $num>>1; 32 $num = $num & 0x7FFFFFFFFFFFFFFF; 33 return r_shift($num, $bit - 1); 34 } 35 } 36 37 function add64($x,$y){ 38 $jw = $x & $y; 39 $jg = $x ^ $y; 40 while($jw) 41 { 42 $t_a = $jg; 43 $t_b = $jw << 1; 44 $jw = $t_a & $t_b; 45 $jg = $t_a ^ $t_b; 46 } 47 return $jg; 48 } 49 50 function MurmurHash64A($key, $seed) { 51 $m = -4132994306676758123; 52 $r = 47; 53 $len = strlen($key); 54 55 $h = $seed ^ (multi64($len, $m)); 56 $bytes = getBytes($key); 57 58 for ($i = 0; $i < ($len / 8) - 1; $i++) { 59 $k = 0; 60 for ($j = 0; $j < 8; $j++) { 61 $k = ($k << 8) | $bytes[$i * 8 + 7 - $j]; 62 } 63 $k = multi64($k, $m); 64 $k ^= r_shift($k, $r); 65 $k = multi64($k, $m); 66 $h ^= $k; 67 $h = multi64($h, $m); 68 } 69 70 $data2_index = $len - $len % 8; 71 switch ($len & 7) { 72 case 7: $h ^= ($bytes[$data2_index + 6]) << 48; 73 case 6: $h ^= ($bytes[$data2_index + 5]) << 40; 74 case 5: $h ^= ($bytes[$data2_index + 4]) << 32; 75 case 4: $h ^= ($bytes[$data2_index + 3]) << 24; 76 case 3: $h ^= ($bytes[$data2_index + 2]) << 16; 77 case 2: $h ^= ($bytes[$data2_index + 1]) << 8; 78 case 1: $h ^= ($bytes[$data2_index + 0]); 79 $h = multi64($h, $m); 80 }; 81 82 $h ^= r_shift($h, $r); 83 $h = multi64($h, $m); 84 $h ^= r_shift($h, $r); 85 86 return $h;
代码见上面:
需要注意的问题是,对PHP来说,没有无符号数,所以会出现负数的问题。
对此可以处理如下
$fp = Fingerprint($model->url); if ($fp > 0) { echo "fp is :".$fp."<br>"; echo "HEX fp is :".dechex($fp)."<br>"; } else { echo "HEX fp is :".dechex($fp)."<br>"; $new = bcadd('18446744073709551616' ,$fp); echo "fp is :".$new.'<br>'; }
判断计算的fp是正还是负,如果是负数,则通过
bcadd('18446744073709551616' ,$fp) 可以将其转成字符串的表示来正确显示输出。