2017-08-10 152 views
0

我正在測試與Python的串行通信,所以我需要將十六進制字符串轉換爲bytearrays。 但現在我遇到了將負值表示爲十六進制符號的問題。例如,假設我想將十六進制16(十進制100)轉換爲一個字節數組;我會用:將負值轉換爲bytearray

myvalue = bytearray.fromhex("16") 

但是,如果我嘗試轉換-100

myvalue = bytearray.fromhex("-16") 

我得到ValueError異常:在位置0

在fromhex發現非十六進制數()ARG具體來說,我必須使用串行API通過USB控制電機旋轉。根據文檔,我可以使用2字節有符號值在-32768和32767之間的範圍內指定角度。

那麼,我該怎麼辦?

+2

十六進制中沒有「 - 」符號,負值只是「表示」。 [閱讀此](https://en.wikipedia.org/wiki/Two%27s_complement) –

+0

此答案將幫助你[這裏](https://stackoverflow.com/questions/7822956/how-to-convert-negative -integer值對十六進制中的Python)。它顯示瞭如何將負數十進制數轉換爲十六進制表示。一旦你可以做到這一點,你只需將結果作爲字符串傳遞給'bytearray.fromhex'。 –

+0

十六進制16根本不是十進制100。它是'1 * 16 ** 1 + 6 * 16 ** 0 = 22'。另外,bytearray使用無符號字節,並沒有負數的概念。您可能想要查看結構或數組模塊。你想達到什麼目的? –

回答

1

當您使用bytearray.fromhex("16")時,您使用十六進制表示法來描述所需的位模式。在一個位模式中,我們所說的符號純屬傳統。所以正確的表示取決於接收過程是否期待有符號的字節(可以表示數字-128到127)。如果是,那麼它可能會期待一個補碼的表示。二進制補充的配方是「翻轉位並加1」。因此,爲了表示-1,你以二進制0000 0001開始,翻轉這些位得到1111 1110並加1得到1111 11110xFF)。同樣,爲了表示-100,你以二進制0110 01000x64,十進制100)開始,翻轉這些位得到1001 1011並加1得到1001 11000x9C)。

正如你所看到的,我有一個問題,你用十進制100等同0x16在我的書,0x16是十進制22:0x64是十進制100如上所示,0x64二進制補碼是0x9C。從-100那裏做到這一點:

>>> bytearray([256-100]) 
bytearray(b'\x9c') 

也就是說在Python比翻轉位和添加1

要表示2字節負數容易,你需要做的事情類似。要獲得7位整數(最多127)的二進制補碼,可以從256中減去。要從65,536(而不是 32,767)中減去15位整數的二進制補碼(最多32,767)。

要表達10,000的負角度,請執行此操作65,536 - 10,000 = 55,536。該位模式爲0xD8F0,即bytearray([0xd8, 0xf0])

與負字節一樣,接收器是否會將該位模式解釋爲55,536或-10,000。您正在通話的設備需要一個有符號的16位整數(範圍-32768..32767),因此可以依靠它來將位模式0xD8F0解釋爲-10,000而不是55,536。沒有值的衝突,因爲55,536不在允許範圍內。

+0

符號的存在或不存在實際上與基數無關,而Python的文字實際上並不包含符號(它是一元否定運算符)。二進制補碼使用模運算來表示特定大小內的負範圍。使用具有符號表示的類型(如'array.array('b',[-100])或'struct.pack('b',-100)')可能更合適。 –

+0

所以,根據你的例子,156和-100有相同的十六進制值...我是對嗎? – Ministry

+0

是的,從表示156的無符號字節與表示-100的有符號字節具有相同的位模式。正如一個代表-1的帶符號的16位整數具有與代表65535的無符號16位整數相同的位模式('0xFFFF')。在每種情況下,由接收過程決定它將解釋哪種方式將解釋什麼它會得到。 – BoarGules