First, `(-1 >>> 0) === (2**32 - 1)`

which I expect is due to adding a new zero to the left, thus converting the number into 33-bit number?

But, Why is `(-1 >>> 32) === (2**32 - 1)`

as well, while I expect it (after shifting the 32-bit number 32 times and replacing the Most Significant Bits with zeros) to be 0.

Shouldn’t it be equal `((-1 >>> 31) >>> 1) === 0`

? or Am I missing something?

## Advertisement

## Answer

When you execute `(-1 >>> 0)`

you are executing an unsigned right shift. The unsigned here is key. Per the spec, the result of `>>>`

is always unsigned. `-1`

is represented as the two’s compliment of `1`

. This in binary is all `1`

s (In an 8 bit system it’d be `11111111`

).

So now you are making it unsigned by executing `>>> 0`

. You are saying, “shift the binary representation of `-1`

, which is all `1`

s, by zero bits (make no changes), but make it return an unsigned number.” So, you get the value of all `1`

s. Go to any javascript console in a browser and type:

console.log(2**32 - 1) //4294967295 // 0b means binary representation, and it can have a negative sign console.log(0b11111111111111111111111111111111) //4294967295 console.log(-0b1 >>> 0) //4294967295

Remember `2 **`

any number minus `1`

is always all ones in binary. It’s the same number of ones as the power you raised two to. So `2**32 - 1`

is 32 `1`

s. For example, two to the 3rd power (eight) minus one (seven) is `111`

in binary.

So for the next one `(-1 >>> 32) === (2**32 - 1)`

…. let’s look at a few things. We know the binary representation of `-1`

is all `1`

s. Then shift it right one digit and you get the same value as having all `1`

s but precede it with a zero (and return an unsigned number).

console.log(-1 >>> 1) //2147483647 console.log(0b01111111111111111111111111111111) //2147483647

And keep shifting until you have 31 zeros and a single `1`

at the end.

console.log(-1 >>> 31) //1

This makes sense to me, we have 31 `0`

s and a single `1`

now for our 32 bits.

So then you hit the weird case, shifting one more time should make zero right?

Per the spec:

6.1.6.1.11 Number::unsignedRightShift ( x, y ) Let lnum be ! ToInt32(x). Let rnum be ! ToUint32(y). Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F. Return the result of performing a zero-filling right shift of lnum by shiftCount bits. Vacated bits are filled with zero. The result is an unsigned 32-bit integer.

So we know we already have `-1`

, which is all `1`

s in twos compliment. And we are going to shift it per the last step of the docs by `shiftCount`

bits (which we think is 32). And `shiftCount`

is:

Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F.

So what is `rnum & 0x1F`

? Well `&`

means a bitwise `AND`

operation. `lnum`

is the number left of the `>>>`

and `rnum`

is the number right of it. So we are saying `32 AND 0x1F`

. Remember 32 is `100000`

. `0x`

is hexadecimal where each character can be represented by `4`

bits. `1`

is `0001`

and F is `1111`

. So `0x1F`

is `00011111`

or `11111`

(`31`

in base 10, `2**5 - 1`

also).

console.log(0x1F) //31 (which is 11111) 32: 100000 & 0x1F: 011111 --------- 000000

The number of bits to shift if zero. **This is because the leading 1 in 32 is not part of the 5 most significant bits! 32 is six bits.** So we take 32

`1`

s and shift it zero bits! That’s why. The answer is still 32 `1`

s.On the example `-1 >>> 31`

this made sense because 31 is `<= 5`

bits. So we did

31: 11111 & 0x1F: 11111 ------- 11111

And shifted it `31`

bits…. as expected.

Let’s test this further…. let’s do

console.log(-1 >>> 33) //2147483647 console.log(-1 >>> 1) //2147483647

That makes sense, just shift it one bit.

33: 100001 & 0x1F: 011111 --------- 00001

So, go over `5`

bits with a bitwise operator and get confused. Want to play stump the dummy with a person who hasn’t researched the ECMAScript to answer a stackoverflow post? Just ask why are these the same.

console.log(-1 >>> 24033) //2147483647 console.log(-1 >>> 1) //2147483647

Well of course it’s because

console.log(0b101110111100001) // 24033 console.log(0b000000000000001) // 1 // ^^^^^ I only care about these bits!!!