Negative numbers to binary string in JavaScript

2019-01-13 02:06发布

问题:

Anyone knows why javascript Number.toString function does not represents negative numbers correctly?

//If you try
(-3).toString(2); //shows "-11"
// but if you fake a bit shift operation it works as expected
(-3 >>> 0).toString(2); // print "11111111111111111111111111111101"

I am really curious why it doesn't work properly or what is the reason it works this way? I've searched it but didn't find anything that helps.

回答1:

Short answer:

  1. The toString() function basically takes the decimal, converts it to binary and adds a "-" sign.

  2. A zero fill right shift converts it's operand to a 32 signed bit integer in two complements format.

A more detailed answer:

Question 1:

//If you try
(-3).toString(2); //show "-11"

It's in the function .toString(). When you output a number via .toString():

Syntax

numObj.toString([radix])

If the numObj is negative, the sign is preserved. This is the case even if the radix is 2; the string returned is the positive binary representation of the numObj preceded by a - sign, not the two's complement of the numObj.

So basically it takes the decimal, converts it to binary and adds a "-" sign.

  1. Base 10 "3" converted to base 2 is "11"
  2. Add a sign gives us "-11"

Question 2:

// but if you fake a bit shift operation it works as expected
        (-3 >>> 0).toString(2); // print "11111111111111111111111111111101"

A zero fill right shift converts it's operand to a 32 signed bit integer.

The operands of all bitwise operators are converted to signed 32-bit integers in two's complement format.



回答2:

-3 >>> 0 (right logical shift) coerces its arguments to unsigned integers, which is why you get the 32-bit two's complement representation of -3.

http://en.wikipedia.org/wiki/Two%27s_complement

http://en.wikipedia.org/wiki/Logical_shift



回答3:

var binary = (-3 >>> 0).toString(2); // coerced to uint32

console.log(binary);

console.log(parseInt(binary, 2) >> 0); // to int32

on jsfiddle

output is

11111111111111111111111111111101
-3