【问题标题】:Why is PHP base_convert giving a different result to the same MYSQL function?为什么 PHP base_convert 对同一个 MYSQL 函数给出不同的结果?
【发布时间】:2012-10-17 14:14:20
【问题描述】:

我整理了一个PHP函数如下:

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() 与我在 MySQL 查询中从 RIGHT() 返回的值匹配。但是,当我运行 CONV() 时,我得到的值与从 base_convert() 生成的值不同。

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

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

【问题讨论】:

  • php.net> base_convert() 可能由于与使用的内部“double”或“float”类型相关的属性而在大数字上失去精度。有关更多具体信息和限制,请参阅手册中的浮点数部分。
  • 为什么不尝试另一种方法来实现数字哈希?
  • @Mogria Spot on,这对我很有帮助,并为我指明了这条评论的方向fr2.php.net/manual/en/function.base-convert.php#109660,它的功能更精确。刚刚测试它,它返回相同的值。添加您的评论作为答案,我会将其标记为正确。
  • 只对哈希进行索引可能更有意义。即使是 SHA1,十六进制格式也只有 40 个字节。
  • @tadman 使用这种方法,我可以将它存储为一个 BIGINT,它只有 8 个字节。我也不需要精确的唯一性,只需要提高效率并将冲突降至最低即可。

标签: php mysql


【解决方案1】:

我查看了PHP Manualbase_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 库,因为它使用字符串来存储数字而不是整数/浮点数等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    • 2015-12-23
    • 2014-12-20
    • 1970-01-01
    相关资源
    最近更新 更多