【Python】2進数・16進数・ビット演算の扱い方
はじめに
この記事では、2進数・16進数・ビット演算をPython3で試しながら理解を深めていく。Python2.xとPython3.xでは、ビットの扱いにかなり違いがあるので注意する必要がある。
ビットと数
このプログラムは、1ビットから32ビットまでの各ビットにおける最大長を、10進数・2進数・16進数で表示するプログラムである。
for i in range(2, 34):
n = i - 1
print("======= {bit}bit =======".format(bit=n))
deci = pow(2, n) - 1
print(deci, bin(deci), hex(deci))
print()
プログラムの結果を表にしてみよう。
| bit | 10進数 | 2進数 | 16進数 |
|---|---|---|---|
| 1 | 1 | 0b1 | 0x1 |
| 2 | 3 | 0b11 | 0x3 |
| 3 | 7 | 0b111 | 0x7 |
| 4 | 15 | 0b1111 | 0xf |
| 5 | 31 | 0b11111 | 0x1f |
| 6 | 63 | 0b111111 | 0x3f |
| 7 | 127 | 0b1111111 | 0x7f |
| 8 | 255 | 0b11111111 | 0xff |
| 9 | 511 | 0b111111111 | 0x1ff |
| 10 | 1023 | 0b1111111111 | 0x3ff |
| 11 | 2047 | 0b11111111111 | 0x7ff |
| 12 | 4095 | 0b111111111111 | 0xfff |
| 13 | 8191 | 0b1111111111111 | 0x1fff |
| 14 | 16383 | 0b11111111111111 | 0x3fff |
| 15 | 32767 | 0b111111111111111 | 0x7fff |
| 16 | 65535 | 0b1111111111111111 | 0xffff |
| 17 | 131071 | 0b11111111111111111 | 0x1ffff |
| 18 | 262143 | 0b111111111111111111 | 0x3ffff |
| 19 | 524287 | 0b1111111111111111111 | 0x7ffff |
| 20 | 1048575 | 0b11111111111111111111 | 0xfffff |
| 21 | 2097151 | 0b111111111111111111111 | 0x1fffff |
| 22 | 4194303 | 0b1111111111111111111111 | 0x3fffff |
| 23 | 8388607 | 0b11111111111111111111111 | 0x7fffff |
| 24 | 16777215 | 0b111111111111111111111111 | 0xffffff |
| 25 | 33554431 | 0b1111111111111111111111111 | 0x1ffffff |
| 26 | 67108863 | 0b11111111111111111111111111 | 0x3ffffff |
| 27 | 134217727 | 0b111111111111111111111111111 | 0x7ffffff |
| 28 | 268435455 | 0b1111111111111111111111111111 | 0xfffffff |
| 29 | 536870911 | 0b11111111111111111111111111111 | 0x1fffffff |
| 30 | 1073741823 | 0b111111111111111111111111111111 | 0x3fffffff |
| 31 | 2147483647 | 0b1111111111111111111111111111111 | 0x7fffffff |
| 32 | 4294967295 | 0b11111111111111111111111111111111 | 0xffffffff |
ビット演算
ここからはPython3で、基本的なビット演算を行っていく。
変数の定義
次のように変数を定義した。変数bはaよりも1だけ大きい数である。
a = 0b1111111 # 0x7f
b = 0b10000000 # 0x80
c = 0b10101010
assert a == 127, a
assert b == 128, b
加算
s = bin(a + 1)
assert s == bin(b), s
OR演算
s = bin(a | b)
assert s == bin(0xff), s
AND演算
s = bin(a & b)
assert s == bin(0), s
XOR演算
s = bin(b ^ c)
assert s == bin(0b101010), s
ビットの反転
ただし、Pythonは整数の桁が無制限のため注意が必要。
s = ~a
assert s == -(a + 1), s
シフト演算
s = bin(a << 2)
assert s == bin(0b111111100), s
s = bin(b >> 4)
assert s == bin(0b1000), s
s = bin(b >> 10)
assert s == bin(0b0), s
構造体パッキング
structモジュールを使うと、Pythonの値とPython bytesオブジェクトとして表されるC言語の構造体データとの間の変換できるようになる。バイナリーデータを扱うときは、次の表のCとPythonとの対応が重要となってくる。structモジュールでは、書式文字列をつかってCとPythonの値を変換する。
参考 https://docs.python.org/ja/3.7/library/struct.html
| 文字 | バイトオーダ | サイズ | アラインメント |
|---|---|---|---|
| @ | native | native | native |
| = | native | standard | none |
| < | リトルエンディアン | standard | none |
| > | ビッグエンディアン | standard | none |
| ! | ネットワーク(= ビッグエンディアン) | standard | none |
| フォーマット | Cの型 | Pythonの型 | 標準のサイズ |
|---|---|---|---|
| c | char | 長さ1の文字列 | 1 |
| b | signed char | integer | 1 |
| B | unsigned char | integer | 1 |
| ? | _Bool | 真偽値型(bool) | 1 |
| h | short | integer | 2 |
| H | unsigned short | integer | 2 |
| i | int | integer | 4 |
| I | unsigned int | integer | 4 |
| l | long | integer | 4 |
| L | unsigned long | integer | 4 |
| q | long long | integer | 8 |
| Q | unsigned long long | integer | 8 |
| f | float | float | 4 |
| d | double | float | 8 |
| s | char[] | string | |
| p | char[] | string | |
| P | void * | integer |