Cheng - 5 months ago 7
Javascript Question

# Javascript right shift a negative number

Here is the snippet:

``````var i = 101;
console.log('101: ' +  i.toString(2));
console.log('101 >> 1: ' + (i >> 1).toString(2));

var l = -101;
console.log('-101: ' + l.toString(2));
console.log('-101 >> 1: ' + (l >> 1).toString(2));'
``````

Output:

``````"101: 1100101"
"101 >> 1: 110010"
"-101: -1100101"
"-101 >> 1: -110011"
``````

Why
`-101 >> 1`
is
`-110011`
`-110010`
?

Update: the book Professional javaScript for Web Developers explains how js stores a negative number:

1. get the binary representation of the absolute value of the negative number

2. replace 0s with 1s and 1s with 0s

3. add 1 to the result of step 2

So in my case
`-101 >> 1`
, we first convert -101 to its binary representation:

1. The binary representation of Math.abs(-101) is:

0000 0000 0000 0000 0000 0000 0110 0101

2. invert the 0s and 1s:

1111 1111 1111 1111 1111 1111 1001 1010

3. add 1 to the end:

1111 1111 1111 1111 1111 1111 1001 1011

4. Now, shift it to the right by 1:

1111 1111 1111 1111 1111 1111 1100 1101

The binary above should be the correct result of
`-101 >> 1`
, but when logging a negative number's binary representation, Javascript simply puts a negative sign in front of the binary representation of the positive number:

``````var x = 15;
console.log(x.toString(2)); // output: 1111

var y = -15;
console.log(y.toString(2)); // output: -1111
``````

For our example, this means that when logging the result of
`-101 >> 1`
, JS will output
`minus sign`
+
`the binary representation of the positive number`
. But the positive number is not
`101 >> 1`
because
`101 >> 1`
gives you:

``````(101 >> 1).toString(2);  // output: 110010
(-101 >> 1).toString(2); // output: -110011, not -110010!
``````

To get the correct result, we have to reverse the aforementioned step 1-3:

``````1111 1111 1111 1111 1111 1111 1100 1101   // this is the result we get from step 4
``````

Reverse step 3 by subtracting 1, we get:

``````1111 1111 1111 1111 1111 1111 1100 1100
``````

Reverse step 2 by invert 0s and 1s:

``````0000 0000 0000 0000 0000 0000 0011 0011
``````

Reverse step 1 by converting this binary to integer:

``````parseInt(110011, 2); // output: 51
``````

Finally, when JS logs the result of
`-101 >> 1`
, it will be
`minus sign`
+
`the binary representation of 51`
which is:

``````(51).toString(2);        // output:  110011
(-101 >> 1).toString(2); // output: -110011
``````

Remember that negative numbers are stored as a 2s-complement. For simplicity, let's say it's a 1-byte signed integer, then -101 would be stored as

``````1 0000 0000 (256)
- 0110 0101 (101)
= 1001 1011 (155 if it were unsigned, -101 in signed)
``````

When bit-shifting a negative number, you right-pad with `1`s instead of `0`s (otherwise you'd lose the sign bit), so the result is:

``````  1001 1011
>> 1
= 1100 1101
``````

That is 205 if it were an unsigned integer. Then 2s-complement it back to solve `256 - x = 205` => `x = 51`

Ta-da? :D

Source (Stackoverflow)