在javascript中使用按位运算符

时间:2013-02-04 19:30:51

标签: javascript

我在javascript中创建一个位掩码。它适用于第0位到第14位。当我只将第15位设置为1.它产生整数值“-2147483648”而不是“2147483648”。我可以通过返回第15位的硬编码“2147483648”来做一个特殊情况的黑客攻击,但我想知道正确的方法。

示例代码:

function join_bitmap(hex_lower_word, hex_upper_word)
{
    var lower_word = parseInt(hex_lower_word, 16);
    var upper_word = parseInt(hex_upper_word, 16);
    return (0x00000000ffffffff & ((upper_word<<16) | lower_word));
}

当hex_lower_word为“0x0”且hex_upper_word为“0x8000”而不是2147483648时,上面的代码返回-2147483648

3 个答案:

答案 0 :(得分:3)

原因是因为Javascript的位移操作使用带符号的32位整数。所以,如果你这样做:

0x1 << 31   // sets the 15th bit of the high word

它会将符号位设置为1,这意味着否定。

另一方面,你可以得到你想要的结果而不是比特移位,你可以得到你想要的结果:

1 * Math.pow(2, 31)

答案 1 :(得分:2)

原因是,您正在设置sign bit ...

2147483648为1后跟31个二进制零...

当您进行按位操作时,输出始终是带符号的32位数,这使得第32位成为符号位,因此您得到负数...

<强>更新

(upper_word * Math.pow(2, 16))

会给出正面2147483648

但是,你仍然有OR操作,这使我们回到原点......

答案 2 :(得分:1)

如前所述,按位运算符是32位有符号的。因此,如果在你设置第31位的任何一点上,事情将会出现严重错误。

在您的代码中,表达式

(upper_word<<16) | lower_word)
由于括号,首先评估

,并且由于upper_word设置了最高位,因此您现在将具有负数(0x80000000 = -2147483648

解决方法是确保不将1移到第31位 - 所以你必须在移位之前将高位字的第15位设置为零:

mask15 = 0x7fff;
((upper_word&mask15)<<16|lower_word)

这将照顾“太大的数字变得消极”,但它不会完全解决问题 - 它只会给出错误的答案!要回到正确答案,您需要在答案中设置第31位,如果在upper_word中设置了第15位:

bit15 = 0x8000;
bit31 = 0x80000000;
answer = answer + (upper_word & bit15)?bit31:0; 

然后重写的函数变为:

function join_bitmap(hex_lower_word, hex_upper_word)
    {
        var lower_word = parseInt(hex_lower_word, 16);
        var upper_word = parseInt(hex_upper_word, 16);
        var mask15 = 0x7fff;
        var bit15 = 0x8000;
        var bit31 = 0x80000000;
        return 0xffffffff & (((upper_word&mask15)<<16) | lower_word) + ((upper_word & bit15)?bit31:0);
    }

不仅有一个“硬编码的特殊情况” - 大约有20亿左右。这照顾了所有这些。