4

我在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

有谁知道,问题可能出在哪里?它们看起来一样,但显然它们不是。

4

3 回答 3

3

Javascript 中的<<运算符将数字参数转换为 32 位有符号整数,而不是 IEEE 754 双精度数。

要修复您的 PHP 代码,您将(至少)需要在<<对它执行任何其他操作之前屏蔽操作的结果。

下面的代码产生与在(64 位)MacOS X 10.8.4 上使用 PHP 5.3.15 输入“示例”的 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是无操作的。与自身“与”的数字将产生相同的数字。

于 2013-07-17T20:40:32.940 回答
1

hash()是我用 hash1 测试过的 php 的保留函数,两者都提供相同的结果

使用测试:

PHP 结果:3556498

Javascript:3556498

于 2013-07-17T20:03:35.770 回答
1

在 JavaScript 中,在使用字符串“example”的第 6 次迭代中,结果$hash << 5为负数 ( 96947249 << 5-> -1192655328)。在 PHP 中,它是3102311968.

问题在于,在 JavaScript 中,<<运算符会导致操作数在内部转换为有符号的 32 位整数。有符号 32 位整数的最大值是2147483647. 循环中该点的操作超过该阈值,导致溢出。

在 PHP 中,最大值在 32 位系统中似乎相同 ( 2147483647),但在 64 位系统中要大得多。http://php.net/manual/en/language.types.integer.php(靠近底部)

演示:http : //phpfiddle.org/main/code/mga-i8bhttp://jsfiddle.net/YJRA4/

关于按位运算符和整数的大量信息(希望能更好地解释我在说什么):https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

于 2013-07-17T20:30:30.547 回答