2進数・16進数とビット数
数の表記が変わっても値が同じであることと、ビット数で表せる範囲を学びます。
説明
普段使う10進数は0〜9の10種類の数字で数を表します。コンピューターでよく使う2進数は0と1、16進数は0〜9とA〜Fを使います。A〜Fは10〜15に当たります。どの表記も同じ整数を表せますが、各桁が意味する大きさが違います。
このモジュールでは、例として10進数165を2進数と16進数で表示し、各桁から元の値を求めます。続いて、4ビットと8ビットで表せる最大値を調べます。0を足して表示をそろえることと、扱う数値の範囲を制限することの違いまで説明します。
1165を三つの表記で表示
2進数の一桁を1ビットと呼びます。まず、10進数165を一つの変数に保存し、2進数と16進数でも表示します。
value = 16510進数の整数を保存; value, bin(value), hex(value)10進・2進・16進で表示165、0b10100101、0xa5が表示されます。0bは2進数、0xは16進数を示す接頭辞で、値そのものの桁には含みません。表記が変わっても、どれも同じ165です。
2接頭辞と0埋め
バイト列などを表示するときは、接頭辞を省き、桁数をそろえることがあります。1バイトは8ビットで、16進数では2桁に相当します。
format(value, '08b')最低8桁の2進数, format(value, '02X')最低2桁の16進数10100101とA5です。08bは最低8桁の2進表記、02Xは最低2桁の大文字の16進表記です。この指定は表示を整えるもので、整数の値は変更しません。
3各ビットが表す大きさ
2進数では、右から1、2、4、8と桁の重みが2倍ずつ増えます。165の各ビットについて、位置・重み・0か1かを表示します。
bits = format(value, '08b')8桁のビット列; [(7-i, 2**(7-i), int(b)位置・重み・ビットの値) for i, b in enumerate(bits)各桁を順に処理]1になっているのは重み128、32、4、1の桁です。先頭の位置を7、末尾を0としたとき、位置nの重みは2ⁿになります。
4ビット列から整数に戻す
各桁の重みに0または1を掛け、すべて足すと元の整数になります。変換関数の結果と、この計算結果を並べます。
sum(int(b) * 2**(7-i) for i, b in enumerate(bits))各桁の値を合計, int(bits, 2)文字列を2進数として変換どちらも165です。128+32+4+1という計算が、10100101を2進数として解釈する処理に相当します。
54ビットと16進数1桁の対応
4ビットの組合せは2⁴=16通りです。そのため16進数の0〜Fと一対一に対応します。0〜15の対応表を作ります。
print('dec bin hex')列名を表示; print('\n'.join(f'{n:>3} {n:04b} {n:X}' for n in range(16)))0〜15の全対応を表示0000が0、1001が9、1010がA、1111がFです。2進数から16進数へ直すときは、右から4ビットずつ区切って置き換えられます。
68ビットを4ビットずつに分ける
165のビット列を前半と後半に分け、各4ビットを整数に変換します。
high, low = bits[:4], bits[4:]前半と後半の4ビット; high, low, int(high, 2), int(low, 2)ビット列と各値を表示1010が10、0101が5なので、16進数ではA5です。16進数の左の桁は16倍の重みを持つため、10×16+5=165になります。
7ビット数と最大値
符号なし整数では、すべてのビットが1のとき最大値になります。1〜8ビットについて、組合せ数と最大値を並べます。
[(width, 2**width, 2**width - 1ビット数・組合せ数・最大値) for width in range(1, 9)1〜8ビットを列挙]4ビットは16通りで0〜15、8ビットは256通りで0〜255です。0も一つの値として数えるため、最大値は組合せ数より1小さくなります。
8上限を超えた整数に必要なビット数
255と、その次の256を2進数にします。必要な桁数も調べます。
[(n, bin(n), n.bit_length()値・2進表記・必要なビット数) for n in (255, 256)境界の二つの値]255は11111111の8ビット、256は100000000の9ビットです。8ビットの格納場所に256をそのまま入れることはできません。
9表示幅の指定では値を切り捨てない
8桁の表示を指定したまま、9ビット必要な256を表示します。
format(256, '08b')最低8桁で表示, int(format(256, '08b'), 2)表示結果を整数に戻す100000000と256になりました。08bの8は最低桁数なので、9桁の値は9桁のままです。表示上の0埋めと、保存先のビット幅の制限は別の処理です。
まとめ
同じ165は、2進数で10100101、16進数でA5です。各桁の重みを使えば、どの表記からも同じ値が得られます。
符号なしのnビット整数は0〜2ⁿ−1を表せます。桁数をそろえる表示指定だけでは、この範囲に値を制限できません。
操作履歴と解説を振り返れます。
Python 3
value = 165; value, bin(value), hex(value)(165, '0b10100101', '0xa5')
format(value, '08b'), format(value, '02X')('10100101', 'A5')bits = format(value, '08b'); [(7-i, 2**(7-i), int(b)) for i, b in enumerate(bits)][(7, 128, 1), (6, 64, 0), (5, 32, 1), (4, 16, 0), (3, 8, 0), (2, 4, 1), (1, 2, 0), (0, 1, 1)]
| 重み | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
|---|---|---|---|---|---|---|---|---|
| ビット | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
sum(int(b) * 2**(7-i) for i, b in enumerate(bits)), int(bits, 2)(165, 165)
print('dec bin hex'); print('\n'.join(f'{n:>3} {n:04b} {n:X}' for n in range(16)))dec bin hex 0 0000 0 1 0001 1 2 0010 2 3 0011 3 4 0100 4 5 0101 5 6 0110 6 7 0111 7 8 1000 8 9 1001 9 10 1010 A 11 1011 B 12 1100 C 13 1101 D 14 1110 E 15 1111 F
high, low = bits[:4], bits[4:]; high, low, int(high, 2), int(low, 2)('1010', '0101', 10, 5)[(width, 2**width, 2**width - 1) for width in range(1, 9)][(1, 2, 1), (2, 4, 3), (3, 8, 7), (4, 16, 15), (5, 32, 31), (6, 64, 63), (7, 128, 127), (8, 256, 255)]
[(n, bin(n), n.bit_length()) for n in (255, 256)][(255, '0b11111111', 8), (256, '0b100000000', 9)]
format(256, '08b'), int(format(256, '08b'), 2)('100000000', 256)演習完了