Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why LShift (<<) in Javascript and PHP are not the same?

Tags:

javascript

php

This time it will be about LShift.

In Javascript:

document.write((1732584193 << 5)+"<br />");
document.write((125 << 5)+"<br />");

output:

-391880672
4000

In PHP:

echo (1732584193 << 5)."<br />";
echo (125 << 5)."<br />";

output:

55442694176
4000

With small numbers its all ok, but big integers are not working, why?

like image 280
Kamil Wiśniewski Avatar asked May 01 '26 22:05

Kamil Wiśniewski


1 Answers

This is because you're using a 64-bit version of php. On a 32-bit system the result would be the same.

This is what happens with your bits on a 32-bit system:

source number: 01100111010001010010001100000001
first shift:   11001110100010100100011000000010
2nd:           10011101000101001000110000000100
3rd:           00111010001010010001100000001000
4th:           01110100010100100011000000010000
5th:           11101000101001000110000000100000

The first 5 bits are lost, and the last number has the leftmost bit set, so it's treated as negative. On a 64 bit the picture is different:

source:  0000000000000000000000000000000001100111010001010010001100000001
shifted: 0000000000000000000000000000110011101000101001000110000000100000

In PHP, integers are platform-dependent (32/64 bits), Javascript always uses 32-bit integers for bitwise operations.

To emulate a 32-bit shift on a 64-bit system, shift the result left by 32 bits and then back to the right. This will strip extra bits and cause the sign bit to propagate:

$a = 1732584193;

$b = $a << 5;
$c = (($a << 5) << 32) >> 32;

echo $a, "\n"; # 1732584193
echo $b, "\n"; # 55442694176
echo $c, "\n"; # -391880672
like image 167
georg Avatar answered May 03 '26 10:05

georg