Left shifting with a negative shift count in Javas

2020-03-02 05:47发布

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

3条回答
▲ chillily
2楼-- · 2020-03-02 06:24

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.

查看更多
smile是对你的礼貌
3楼-- · 2020-03-02 06:25

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

查看更多
乱世女痞
4楼-- · 2020-03-02 06:32

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

查看更多
登录 后发表回答