~ JavaScript 中的按位运算符

~ bitwise operator in JavaScript

我有以下代码:

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 因此 return 这个 101110.

This Topic kinda confirm that

所以我不明白我们如何才能得到 -10010?唯一可能的解释是:

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.

但这一切在我的脑海里很模糊,你能知道到底发生了什么吗?

根据 Mozilla 开发者网站上的文档 here。对任何数字 x 进行按位运算会得到 -(x + 1)。例如,~5 产生 -6。这就是为什么您在数字前面得到负号的原因。

JavaScript 的按位运算符将其操作数转换为 32 位有符号整数(通常的 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).

所以你的 10001 是:

00000000 00000000 00000000 00010001

~ 是:

11111111 11111111 11111111 11101110

...这在 2s 补码表示中确实是负数。

你可能会疑惑:如果位模式如上,那为什么b.toString(2)给了你-10010呢?因为它显示的是带符号的二进制文件,而不是实际的位模式。 - 表示负数,10010 表示小数点后 18 位。上面的位模式是如何用 2s 补码位表示的。 (是的,我 确实 必须去检查一下自己!)

在幕后,当 Javascript 进行按位运算时,它会转换为 32 位有符号整数表示形式,并使用它,然后将结果转换回其内部十进制表示形式。

因此,您的输入值 010001 变为 00000000 00000000 00000000 00010001

然后反转:

~00000000 00000000 00000000 00010001 => 11111111 11111111 11111111 11101110

转成十六进制,取反后的值为0xFFFFFFEE,相当于-18的十进制值

由于这是一个值为 -18 的 有符号整数 ,因此该值将转换为 -18 的基础 十进制 表示通过 Javascript.

当 Javascript 尝试将其打印为基数 2 时,它会看到负号和 18 的值,并将其打印为 -10010,因为 10010 是正数 18.

的二进制表示

JavaScript使用32位有符号数,所以

a (010001) (17) is  0000 0000 0000 0000 0000 0000 0001 0001
b = ~a (?) (-18) is 1111 1111 1111 1111 1111 1111 1110 1110

将 -18 打印为 -10010 的原因和获取实际值的方法在这里得到了很好的解释 Link