Reputation: 17934
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
instead of -110010
?
Update: the book Professional javaScript for Web Developers explains how js stores a negative number:
So in my case -101 >> 1
, we first convert -101 to its binary representation:
The binary representation of Math.abs(-101) is:
0000 0000 0000 0000 0000 0000 0110 0101
invert the 0s and 1s:
1111 1111 1111 1111 1111 1111 1001 1010
add 1 to the end:
1111 1111 1111 1111 1111 1111 1001 1011
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
Upvotes: 4
Views: 1412
Reputation: 324730
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
Upvotes: 2