Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 811
kaustav datta Avatar asked May 15 '13 08:05

kaustav datta


People also ask

Can you left shift by a negative number?

The left shift and right shift operators should not be used for negative numbers. The result of is undefined behaviour if any of the operands is a negative number.

What is negative shift count?

Negative shift counts are illegal and cause a ValueError to be raised. A left shift by n bits is equivalent to multiplication by pow(2, n). A long integer is returned if the result exceeds the range of plain integers.

What does << mean in Javascript?

The left shift operator ( << ) shifts the first operand the specified number of bits, modulo 32, to the left. Excess bits shifted off to the left are discarded. Zero bits are shifted in from the right.

What happens when you left shift a number?

The number to the left of the operator is shifted the number of places specified by the number to the right. Each shift to the left doubles the number, therefore each left shift multiplies the original number by 2. Use the left shift for fast multiplication or to pack a group of numbers together into one larger number.


1 Answers

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).

like image 126
Subskybox Avatar answered Oct 15 '22 11:10

Subskybox