2013-02-04 129 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操作,這使我們回到原點......