LoginSignup
2
2

More than 1 year has passed since last update.

Python 符号付き整数を取り扱う

Last updated at Posted at 2021-05-11

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のバージョン依存があるかもしれません。
問題点あれば教えて頂ければ助かります。
また、関数名や変数名のつけ方に悩みました。いい命名方法があれば合わせてご意見お待ちしております。

2
2
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2