Python 符号付き整数(bit数指定)を数値に変換する
Arduinoから直接センサーデータを取得するとき、センサーデータが符号付きの数値(bit数指定)で戻ってきます。
組み込み用の言語であれば符号付き整数を簡単に取り扱う事ができますがPyhotnで計算する場合はそうもいきません。
そのため、符号付き数値(bit数指定)をPythonで扱える数値に変換する必要があります。
16bitの符号付き16進数の場合、下記のような変換結果を期待されます。
0x0001 -> 1
0x0000 -> 0
0xffff -> -1
符号付き数値の具体的なフォーマットは左側bitが符号、そのほかのbitは補数となります。
すなわち、0xffffをビット反転してあげます。
0xffff ^ 0xffff = 0x0000 = 0
その数値に-1してあげれば目的の数値となります
0xffff ^ 0xffff - 1 = 0x0000 -1 = -1
つまり先頭bitの符号を確認し、ビット反転すれば元の数値となる事がわかります。
Pythonのコードで書くとこのようになります。
signed_hex = 0xffff
signed_int = (int(signed_hex^0xffff) * -1)-1 if (signed_hex & 0x8000) else int(signed_hex)
print(signed_int)
実行結果
-1
ただ、このコードは16bitの符号付き整数のみ対応するため、汎用性を上げるためにbit数可変可能な下記のような関数を作ってみました。
def signed_hex2int( signed_hex, digit ):
signed = 0x01 << (digit-1)
mask = 0x00
for num in range(digit):
mask = mask | (0x01<<num)
signed_int = (int(signed_hex^mask)*-1)-1 if (signed_hex & signed) else int(signed_hex)
return signed_int
# test
print (signed_hex2int( 0xf0, 8 )) #8bit
print (signed_hex2int( 0xff00, 16 )) #16bit
print (signed_hex2int( 0xfff000, 24 )) #24bit
print (signed_hex2int( 0xffff0000, 32 )) #32bit
print (signed_hex2int( 0x0f, 8 )) #8bit
print (signed_hex2int( 0x00ff, 16 )) #16bit
print (signed_hex2int( 0x000fff, 24 )) #24bit
print (signed_hex2int( 0x000ffff, 32 )) #32bit
実行結果
-16
-256
-4096
-65536
15
255
4095
65535
挙動が怪しいところがありますので機種依存やPythonのバージョン依存があるかもしれません。
問題点あれば教えて頂ければ助かります。
また、関数名や変数名のつけ方に悩みました。いい命名方法があれば合わせてご意見お待ちしております。