Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

~ bitwise operator in JavaScript

I have the following code :

var a = parseInt('010001',2);
console.log(a.toString(2));
//  10001
var b = ~a;
console.log(b.toString(2));
// -10010

The MSDN Say

~ Performs the NOT operator on each bit. NOT a yields the inverted value (a.k.a. one's complement) of a.

010001 should thus return this 101110.

This Topic kinda confirm that

So I can't understand how we can get -10010 instead ? The only potential explanation is that:

010001 is negated 101110 but he write this -10001 and then for an obscure reason he give me the two complements and -10001 become -10010.

But all this is very obscure in my mind, would you have an idea on what happen precisely.

like image 997
seb_kaine Avatar asked Sep 11 '15 16:09

seb_kaine


2 Answers

JavaScript's bitwise operators convert their operands to 32-bit signed integers (the usual 2's complement), perform their operation, then return the result as the most appropriate value in JavaScript's number type (double-precision floating point; JavaScript doesn't have an integer type). More in §12.5.11 (Bitwise NOT Operator ~) and §7.1.5 (ToInt32).

So your 10001 is:

00000000 00000000 00000000 00010001

which when ~ is:

11111111 11111111 11111111 11101110

...which is indeed negative in 2s complement representation.

You may be wondering: If the bit pattern is as above, then why did b.toString(2) give you -10010 instead? Because it's showing you signed binary, not the actual bit pattern. - meaning negative, and 10010 meaning 18 decimal. The bit pattern above is how that's represented in 2s complement bits. (And yes, I did have to go check myself on that!)

like image 160
T.J. Crowder Avatar answered Oct 30 '22 15:10

T.J. Crowder


Under the covers, when Javascript does bitwise operations, it converts to a 32-bit signed integer representation, and uses that, then converts the result back into its internal decimal representation.

As such, your input value, 010001 becomes 00000000 00000000 00000000 00010001.

This is then inverted:

~00000000 00000000 00000000 00010001 => 11111111 11111111 11111111 11101110

Converted into hex, the inverted value is 0xFFFFFFEE, which is equivalent to the decimal value of -18.

Since this is a signed integer with a value of -18, this value is converted to the underlying decimal representation of -18 by Javascript.

When Javascript tries to print it as a base-2 number, it sees the negative sign and the value of 18, and prints it as -10010, since 10010 is the binary representation of positive 18.

like image 30
Shotgun Ninja Avatar answered Oct 30 '22 14:10

Shotgun Ninja