kaustav datta
kaustav datta

Reputation: 705

Left shifting with a negative shift count in Javascript

A thing which I noticed in Javascript -

a << -1

Returns 0 when a = even.
Returns -2147483648 when a = odd.

Similarly, different values are returned when -1 is changed to some other -ve number. Can someone explain what bit operations are taking place under the hood ? Or is the behavior undefined ?

Thanks

EDIT

Also shouldn't Zero-fill right shift i.e. -2 >>> 1 return 7 ?

-2 = 1110. After, right shift with zero-fill, it should give 0111 = 7

but a = -2; console.log(a >>> 1); returns 2147483647

Upvotes: 8

Views: 2299

Answers (3)

Subskybox
Subskybox

Reputation: 657

I too wondered about this which is how I landed here. I’ve done a little research and figured out the behavior. Essentially JavaScript treats the operand and shift value as sequences of bits rather than as numbers. It works with 32 bit integers (floats get truncated) and the maximum shift is 32 bits. If we shift by a number greater than 32, all the bits would shift out, resulting in zero. To ensure the shift is less than or equal to 32, JavaScript truncates the 5 least significant bits [a << (b&0x1F)] or possibly with the modulus method [a << (b%32)] which yields the same result.

With that out of the way, think of the negative number you are shifting by as a sequence of bits, not a negative number (i.e. -1). In this case b = -1 = 0xFFFFFFFF. Since this number is larger than 32, it is truncated 0xFFFFFFFF & 0x1F = 31 or 0xFFFFFFFF % 32 = 31.

So in your example “a" gets shifted all the way from the least significant bit to the most significant bit (the sign bit). Therefor the result of the shift is either 0x00000000 or (0x80000000 = -2147483648) depending on whether the operand had the 1 bit set (odd or even).

Upvotes: 9

RobG
RobG

Reputation: 147413

The LeftShift operator adds zeros to the right of the binary representation of a number, shifting the bits to the left. Only the 5 least significant digits of the additive expression are used. So:

var x = 5         // 101

alert( x << 1  ); // 1010 = 10

alert( x << 2  ); // 10100 = 20

alert( x << 3  ); // 101000 = 40

alert( x << 4  ); // 1010000 = 80

alert( x << 64 ); // 101 = 5

The last expression returns 5 as shift only uses the last 5 bits of the the additive expression, which is 1000000 so only the 00000 part is used.

Upvotes: 0

kaustav datta
kaustav datta

Reputation: 705

Got the answer to the second part of my question i.e. -2 >>> 1 = 7.

Javascript always deals with 32 bits. So when I do -2 >>> 1, what really happens under the hood is - 11111111111111111111111111111110 >>> 1 which gives 01111111111111111111111111111111 = (2147483647)base10

Upvotes: 0

Related Questions