over 1 year ago

I run into a problem today, 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?

Here is what I learned by reading Professional JavaScript for Web Developers:

When js stores a negative number, it does the following things:

  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:

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 should be in the format of minus sign + the binary representation of 51:

(51).toString(2);        // output:  110011

(-101 >> 1).toString(2); // output: -110011
← Django admin login keeps redirecting back to login page JavaScript for loop vs forEach →
 
comments powered by Disqus