反向位:为什么它给我一个负值?

时间:2015-07-15 21:33:54

标签: javascript bit-manipulation bitwise-operators

var reverseBits = function(n) {
    var re = 0;
    for( var i = 0; i < 32; i++ ) {
        re = (re << 1) | (n & 1);
        n >>>= 1;
    }

    return re;
};

这是我在Javascript中反转位的代码,但是当n = 1时,它给出-2147483648(-10000000000000000000000000000000),它不应该是正数吗?我哪里错了?

2 个答案:

答案 0 :(得分:2)

您获得负数的原因是计算机存储负数和正数。最高有效位(具有最大值的位)用于符号编号,以确定数字是负数还是正数。如果此位是0,那么它是正数。如果它是1,那么它是否定的。计算机使用名为2's compliment的技术将数字从负数转换为正数。以下是它的工作原理:

在您的示例中,您将号码1分配给n。在32位计算机中,二进制文件看起来像这样:

0000 0000 0000 0000 0000 0000 0000 0001

反转你的位后,你的二进制文件如下所示:

1000 0000 0000 0000 0000 0000 0000 0000

如果您拿出二进制计算器并输入此数字并将其转换为十进制数,则会看到其值2147483648。因为最左边的位是1,所以它是负数。由于Javascript只有通用var变量,因此它假定您需要签名结果。 JavaScript中的>>>运算符称为zero-fill right shift,并使用操作数0>>> 0),告诉Javascript您想要无符号结果。

如果你好奇(或者这篇文章的其他读者很好奇),这里是基于二进制的计算机如何处理负数。假设您要存储值-96。计算机如何存储?首先,忽略这个标志。二进制文件中的96如下所示:

0000 0000 0000 0000 0000 0000 0110 0000

接下来,计算机会执行2次恭维。这是通过首先反转每个位(1&#39; s变为0&0;以及0&#39; s变为1&#39; s)来实现的:

1111 1111 1111 1111 1111 1111 1001 1111

最后,您只需添加1,如下所示:

1111 1111 1111 1111 1111 1111 1010 0000

在内部,这就是它存储在您计算机内存中的方式。这相当于4,294,967,200-96

答案 1 :(得分:1)

  

不应该是正数吗?我哪里错了?

不,不应该。除>>>之外的所有按位运算符都使用带符号的 32位整数,其中前导1(以二进制补码表示)表示负数。

正如@Icemanind所建议的那样,您可以使用>>>的无符号来修复它并将其“转换”为无符号整数:

return re >>> 0;