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) 可以将其转成字符串的表示来正确显示输出。

 

posted on 2013-03-18 17:30  @且听风吟@  阅读(555)  评论(0)    收藏  举报