Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why bitwise shift with 0 in JavaScript yields weird results in some cases

Just played around with unusual bitwise operations in JavaScript and I got some weird results in some cases:

Usual cases

1 << 0            // returns 1, makes sense
100 << 0          // returns 100, makes sense
100 >> 0          // returns 100, definitely makes sense

But these, when shift by 0 bits, all yield zero

9E99 << 0         // returns 0 ..... Why all bits are cleared?
9E99 >> 0         // returns 0 also  ..... All bits cleared?
Infinity >> 0     // returns 0
Infinity << 0     // returns 0
-Infinity << 0    // returns 0 .... Can't explain why
-0 << 0           // also yields 0 not -0 itself
-0 >> 0           // also resolved to 0

What if Infinity and bitwise shift

1 << Infinity     // returns 1  .. no changes
1024 << Infinity  // returns 1024 .. no changes
1024 >> Infinity  // returns 1024 .. no changes either
Infinity >> Infinity      // 0
Infinity << Infinity      // 0

Those cases above don't make much sense to me. When shift an integer by zero bits, the value doesn't change. But when you shift Infinity by 0 bits, it actually returns you 0. Why?

I thought shifting any numeric value by 0 bit should not change its value, doesn't it?

Further, when shift a small integer value by infinity bits, the value doesn't change at all. But when you shift Infinity by any values, it is replaced by 0 instead.

I'm really curious why these phenomena happen? Is there any specifications or theory that explain these odd behaviors?

like image 274
TaoPR Avatar asked Feb 10 '23 22:02

TaoPR


1 Answers

From the MDN:

The operands of all bitwise operators are converted to signed 32-bit integers in two's complement format.

All numbers in JavaScript are IEEE754 double precision floating point numbers. They're converted to 32 bits integers before being applied bitwise operators.

More precisely, this process is described in ToInt32 in the spec:

enter image description here

As you see, the transformation of Infinities and -0 is precisely described.

This is a binary truncation, which also explains why 9E99 is changed into 0: This is most obvious if you look at the 32 bits at the right of (9E99).toString(2) (paste it in your console, they're all 0).

like image 158
Denys Séguret Avatar answered Feb 12 '23 13:02

Denys Séguret