我在javascript中有这个功能 - 工作正常
// javascript
function myhash(str) {
var hash = 0;
if (str.length == 0) return hash;
for (var i = 0; i < str.length; i++) {
oneChar = str.charCodeAt(i);
hash = ((hash << 5) - hash) + oneChar;
hash &= hash;
}
return hash;
}
我正在尝试将此函数重写为PHP,但是对于相同的输入,它提供的输出与JS中的输出不同。
// php
function myhash($str) {
$hash = 0;
if (strlen($str) == 0) return $hash;
for ($i = 0; $i < strlen($str); $i++) {
$oneChar = ord($str[$i]);
$hash = (($hash << 5) - $hash) + $oneChar;
$hash &= $hash;
}
return $hash;
}
输入和输出示例:
console.log(myhash("example")); // output: -1322970774
echo myhash("example"); // output: 93166309738
有谁知道,问题出在哪里?它们看起来一样,但显然它们不是。
答案 0 :(得分:3)
Javascript中的<<
运算符将数字参数转换为32位有符号整数,而不是IEEE 754双精度。
要修复您的PHP代码,您将(至少)需要屏蔽<<
操作的结果,然后再对其执行任何其他操作。
下面的代码与使用PHP 5.3.15在(64位)MacOS X 10.8.4上输入“example”的JS代码产生相同的结果。它可能不适用于其他测试用例或32位版本的PHP:
function myhash($str) {
$hash = 0;
if (strlen($str) == 0) return $hash;
for ($i = 0; $i < strlen($str); $i++) {
$oneChar = ord($str[$i]);
$tmp = ($hash << 5) & 0xffffffff;
$hash = ($tmp - $hash) + $oneChar;
}
return $hash;
}
注意:行$hash &= $hash
是无操作。与自身“anded”的数字将产生相同的数字。
答案 1 :(得分:1)
答案 2 :(得分:1)
在JavaScript中,在使用字符串“example”的第6次迭代中,$hash << 5
的结果是负数(96947249 << 5
- &gt; -1192655328
)。在PHP中,它是3102311968
。
问题是在JavaScript中,<<
运算符会导致操作数在内部转换为带符号的32位整数。带符号的32位整数的最大值为2147483647
。循环中该点的操作越过该阈值,导致溢出。
在PHP中,32位系统中的最大值似乎相同(2147483647
),但在64位中则更大。 http://php.net/manual/en/language.types.integer.php
(靠近底部)
DEMOS: http://phpfiddle.org/main/code/mga-i8b和http://jsfiddle.net/YJRA4/
关于按位运算符和整数的大量信息(希望能更好地解释我所说的内容):https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators