2013-02-04 130 views
4

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

示例代码:

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)); 
} 

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

+0

你的意思是MSB 15或LSB 15? – ATOzTOA

+5

Javascript按位操作的结果总是[带符号的32位整数](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators#Signed_32-bit_integers)。 – duskwuff

回答

1

由于以前的答案解释,按位运算符是32位的签名。因此,如果在你设置第31位的任何时候,事情将会严重错误。

在代码中,表达

(upper_word<<16) | lower_word) 

第一次评估,因为括号的,由于upper_word具有顶部位设置,你现在有一个负数(0x80000000 = -2147483648

解决方案是为了确保您不会将1转换为位31 - 因此您必须在移位之前将上位字的位15设置为零:

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

这会照顾到“数字太大变负面”,但它不会完全解决问题 - 它只会给出错误的答案!要回到正确的答案,你需要设置31位的答案,当且仅当位15 upper_word设置:

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亿左右。这照顾所有这些。

+0

辉煌的解决方案。我很佩服!非常感谢。 –

+1

感谢您的赞美!操纵位是我的一个爱好...如果你喜欢这个,你可能想看看[这个最近的答案](http://stackoverflow.com/questions/14547087/extracting-bits-with-a-单乘/ 14547307#14547307) – Floris

+0

@FYaqoob - 感谢您抓住马虎的错误,并花时间修复它们! – Floris

3

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

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

它将符号位设置为1,这意味着负面。

在另一方面,而不是位移位你乘以二的幂,你会得到的结果你想要的:

1 * Math.pow(2, 31) 
2

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

2147483648后面31个零二进制... 1

当你正在做一个按位运算,输出总是32位有符号数,这使得第32位的符号位,所以你得到一个负数...

更新

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

将给予积极的2147483648

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