Same function in javascript and php, but different outputs

I have this function in javascript - it works correctly

// 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; } 

And I'm trying to rewrite this function in PHP, but for the same input it gives a different result than the one that JS has.

 // 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; } 

Example input and output:

 console.log(myhash("example")); // output: -1322970774 echo myhash("example"); // output: 93166309738 

Does anyone know where there might be a problem? They look the same, but apparently it is not.

+4
source share
3 answers

The << operator in Javascript converts a numeric parameter to a signed 32-bit integer, not an IEEE 754 double.

To fix your PHP code, you (at least) will need to mask the result of the << operation before doing anything else with it.

The code below gives the same result as the JS code for entering an “example” using PHP 5.3.15 (64-bit) MacOS X 10.8.4. It may not work for other test cases or 32-bit versions of 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; } 

NB: the string $hash &= $hash not an operation. The number "anded" with itself will produce the same number.

+3
source

hash () is a reserved function for php I, tested with hash1, providing the same result

using the test:

PHP result: 3556498

Javascript: 3556498

+1
source

In JavaScript, at the 6th iteration using the string "example", the result $hash << 5 is a negative number ( 96947249 << 5-1192655328 ). In PHP, this is 3102311968 .

The problem is that in JavaScript, the << operator causes the operands to be internally converted to signed 32-bit integers. The maximum value of a signed 32-bit Integer is 2147483647 . An operation at this point in the loop crosses this threshold, causing an overflow.

In PHP, the maximum value seems to be the same ( 2147483647 ) on 32-bit systems, but much more on 64-bit. http://php.net/manual/en/language.types.integer.php (below)

DEMOS: http://phpfiddle.org/main/code/mga-i8b and http://jsfiddle.net/YJRA4/

A lot of information about bitwise operators and integers (hopefully better explains what I'm saying): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

+1
source

Source: https://habr.com/ru/post/1491962/


All Articles