2016-04-14 119 views
3

我對一個名爲OpenBCI的新物聯網項目感興趣,該項目基本上是用於讀取和處理腦波和其他生物數據的開源EEG。在他們的docs中,他們聲稱通過空中傳輸的數據(通過RFDuino)發送24位數據。到了24位值轉換爲32位有符號整數,他們提出以下Java友好Processing代碼:Java中的24位到32位轉換

int interpret24bitAsInt32(byte[] byteArray) { 
    int newInt = (
     ((0xFF & byteArray[0]) << 16) | 
     ((0xFF & byteArray[1]) << 8) | 
     (0xFF & byteArray[2]) 
    ); 

    if ((newInt & 0x00800000) > 0) { 
     newInt |= 0xFF000000; 
    } else { 
     newInt &= 0x00FFFFFF; 
    } 

    return newInt; 
} 

我想我試圖瞭解究竟是怎麼回事。讓我們的代碼的第一個導語:

int newInt = (
    ((0xFF & byteArray[0]) << 16) | 
    ((0xFF & byteArray[1]) << 8) | 
    (0xFF & byteArray[2]) 
); 
  • 爲什麼是安全的假設有輸入3個字節?
  • 0xFF值的重要性是什麼?
  • 左移位的目的是什麼(<<)?

第二段也是一個有點神祕:

if ((newInt & 0x00800000) > 0) { 
    newInt |= 0xFF000000; 
} else { 
    newInt &= 0x00FFFFFF; 
} 
  • 爲什麼newInt & 0x008000000x00800000有什麼意義?
  • 爲什麼if-else基於上述操作的陽性與陰性結果?
  • 0xFF0000000x00FFFFFF是什麼意思?

我想這個功能有很多handwaving和magic,我想更好地理解!

+0

最後一部分是簽名擴展的一個晦澀的方式,else分支是無操作的。更加明顯的是'newInt =(newInt << 8) >> 8' – harold

回答

8

爲什麼安全地假設輸入中有3個字節?

24位/ 8位= 3個字節

什麼是0xFF的值的意義是什麼?

這是一個有點掩碼。 0b11111111二進制。在這種情況下,它被用作將字節值轉換爲int的快速方法。

左移位的目的是什麼(< <)?

一旦在上一條指令中檢索到int值,它將向左移位16位,以獲取int第三個字節的位置(從右邊算起)。這是由於字節數組存儲big-endian格式的字節,其中MSB最先出現。下一個字節僅移位8位以佔用第二個字節的位置,而最後一個字節根本不需要移位,因爲它已經在第一個字節中。

爲什麼newInt & 0x00800000? 0x00800000有什麼意義?

那麼0x80是獲得某個字節的MSB的另一個位掩碼。 0x00800000對應於第三字節的MSB(即byteArray[0]中的字節,其在先前過程中被移位了16位)。這也對應於整個24位值的MSB。

爲什麼if-else基於上述操作的正反結果?

確定24位值的MSB是1還是0會告訴我們它是否爲負數或正數,分別爲two's complement表示法。

0xFF000000和0x00FFFFFF的意義是什麼?

如果數字爲它負的24位代表,我們也希望它是否定的,因爲在補一個32位值,這就是爲什麼我們要填補第四和最後一個字節與0b11111111(0xFF的)使用OR運算符。
如果它已經是正的,那麼第四個字節可以是0x00,以下3個字節與原始24位值相同 - 用0x00FFFFFF掩碼完成。

+0

真棒,真棒答案@James Buck(+1) - 謝謝!只是好奇,如果我在Java中實現它,並且需要單元測試來確認這是否可行或者不是,在哪裏可以找到24位有符號整數和它們相應的32位有符號值,以驗證測試結果?:-)再次感謝! – smeeb

+0

@smeeb那麼你可以選擇任意的24位數字,把它們放在二進制補碼二進制到十進制轉換器中,比如[this](http://www.exploringbinary.com/twos-complement-converter/)。然後你可以把這個相同的二進制數字放在一個3字節的數組中,上面的代碼應該把它轉換成一個32位的整數,其值與計算器完全相同。該代碼將確保任何24位值在轉換爲32位格式時保留其值。 –