一覧CS-01-1 · 数の表現

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

1
value = 165; value, bin(value), hex(value)
(165, '0b10100101', '0xa5')
2
format(value, '08b'), format(value, '02X')
('10100101', 'A5')
3
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)]
165のビット
重み1286432168421
ビット10100101
4
sum(int(b) * 2**(7-i) for i, b in enumerate(bits)), int(bits, 2)
(165, 165)
5
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
6
high, low = bits[:4], bits[4:]; high, low, int(high, 2), int(low, 2)
('1010', '0101', 10, 5)
7
[(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)]
8
[(n, bin(n), n.bit_length()) for n in (255, 256)]
[(255, '0b11111111', 8), (256, '0b100000000', 9)]
9
format(256, '08b'), int(format(256, '08b'), 2)
('100000000', 256)

演習完了