2012-10-17 108 views
2

我已经把一个PHP函数如下:为什么PHP base_convert会给同一个MYSQL函数一个不同的结果?

function keyword_hash($keyword) { 
    return base_convert(substr(md5($keyword), -16), 16, 10); 
} 

此功能的目的是产生,我可以在数据库中存储一个数字的哈希值,并使用了一个查找表(而不是试图索引关键字列)。

在MySQL这个函数的等效如下:

SELECT CONV(RIGHT(MD5('some keyword'), 16), 16, 10); 

我验证过MD5字符串是一样的,和SUBSTR()我回来从RIGHT()的值在匹配MySQL查询。但是,当我运行CONV()时,我得到了与base_convert()生成的值不同的值。

例如,使用keyword_hash("some keyword")会生成值10923672322315740844.但是,使用SELECT CONV(RIGHT(MD5('some keyword'), 16), 16, 10)会生成10923672322315740475,它显示最后三个数字不同。

缺少什么我在这里?它们不应该产生相同的价值吗?

+5

[php.net](http://fr2.php.net/manual/en/function.base-convert.php)> base_convert()可能会因为属性而失去大数精度与使用的内部“double”或“float”类型有关。请参阅手册中的浮点数部分以获取更多具体信息和限制。 – MarcDefiant

+0

为什么不试图用另一种方式来实现数字散列? –

+0

@Mogria Spot on,那是一个很大的帮助,并指出我对这个评论的方向http://fr2.php.net/manual/en/function.base-convert.php#109660,它有一个很棒的功能更精确。刚刚测试过它,并返回相同的值。添加您的评论作为答案,我会将其标记为正确。 –

回答

3

我看了一下PHP Manual页面base_convert()。有以下警告

base_convert()可能会失去对大量精度由于与 到内部“双重”或“浮动”使用类型属性。请参阅手册中的 Floating point numbers section以获取更多 的具体信息和限制。

comments someone后来已经找到了一个解决这个问题(感谢@CraigSefton):

function str_baseconvert($str, $frombase=10, $tobase=36) { 
    $str = trim($str); 
    if (intval($frombase) != 10) { 
     $len = strlen($str); 
     $q = 0; 
     for ($i=0; $i<$len; $i++) { 
      $r = base_convert($str[$i], $frombase, 10); 
      $q = bcadd(bcmul($q, $frombase), $r); 
     } 
    } 
    else $q = $str; 

    if (intval($tobase) != 10) { 
     $s = ''; 
     while (bccomp($q, '0', 0) > 0) { 
      $r = intval(bcmod($q, $tobase)); 
      $s = base_convert($r, 10, $tobase) . $s; 
      $q = bcdiv($q, $tobase, 0); 
     } 
    } 
    else $s = $q; 

    return $s; 
} 

此功能使用bc math库,支持任意精度的数学,因为它使用字符串存储的数字,而不是整数/浮点数等。

相关问题