2 進数と 16 進数

回 1-1 道 1 数と論理と計算量

2 進数は、0 と 1 の 2 つの数字だけで数を表し、桁が 1 つ左へ進むごとに重みが 2 倍になる数の表し方です。16 進数は 0〜9 と A〜F の 16 個の数字を使い、1 桁がちょうど 4 ビット、2 桁で 1 バイトに当たります。8 ビットで表せるのは 256 通りで、0〜255 の範囲を超えると上の桁が器からこぼれます。

数の値と、その数を入れる器の幅を切り分けられるようになります。

なぜ 0 と 1 だけで数が表せるのか

0 と 1 だけでも、桁を並べて重みを決めれば、どんな大きさの数でも表せます。

Web の頁の色は #FF8000 のように書き、エラーの画面には 0x で始まる英数字が並びます。どちらも 16 進数 (16 ごとに桁が上がる数の表し方) です。なぜ普段の 10 進数ではなく、16 進数で書くのでしょうか。

手がかりは、コンピュータが電気の有る無しの 2 つの状態で情報を持つことです。この 1 つ分をビット (0 か 1 かを持つ最小の単位) と呼びます。ビットを 8 個並べたまとまりが 1 バイトです。

ビットはスイッチのオンとオフで、8 個で 1 バイトになる図

8 個のスイッチで表せる数はいくつまでで、それを超える数を入れると何が起きるでしょうか。この回の終わりには、数字と理由で答えられるようになります。

2 進数と 16 進数の仕組み

どの数の表し方も、各桁の数字と桁の重みを掛けて足すと値になります。違うのは、重みが何倍ずつ大きくなるかだけです。

位取りと桁の重み

10 進数の 178 は、1 が 100 の桁、7 が 10 の桁、8 が 1 の桁にあり、1 × 100 + 7 × 10 + 8 × 1 で 178 です。これを位取り (数字を置く場所で重みを決めるやり方) と呼びます。10 進数では、左へ 1 桁進むと重みが 10 倍になります。

2 進数では、左へ 1 桁進むと重みが 2 倍になります。8 ビットの場合、右端から 1、2、4、8、16、32、64、128 の重みが並びます。

桁 (左から)10 進の重み2 進の重み
110000000128
2100000064
310000032
41000016
510008
61004
7102
811

2 進数の 10110010 なら、1 の桁の重み 128、32、16、2 を足して 178 です。下の図でスライダーを 255 まで動かして +1 を入れると、8 個のビットがすべて 0 に戻ります。これが後の節で扱う桁あふれです。

2進数と10進数

10 進数から 2 進数へ、2 進数から 10 進数へ

10 進数を 2 進数に直すには、2 で割って余りを書き留めることを、商が 0 になるまで繰り返します。最後に、余りを下から上へ読みます。

逆に 2 進数を 10 進数に直すには、1 が立っている桁の重みを足します。

向き手順
10 進から 2 進2 で割り、余りを書く。商が 0 になったら、余りを下から読む
2 進から 10 進1 の桁の重み (1、2、4、8…) を足す
2 進から 16 進右から 4 ビットずつ区切り、それぞれを 16 進の 1 桁にする
16 進から 2 進16 進の 1 桁を 4 ビットに戻して並べる

16 進数は 4 ビットずつの区切り

16 進数の 1 桁は、ちょうど 4 ビットに当たります。4 ビットで表せるのは 16 通りで、16 進数の 1 桁が持つ 0〜9 と A〜F の 16 個と同じだからです。

16 進10 進2 進 (4 ビット)
000000
110001
991001
A101010
B111011
C121100
D131101
E141110
F151111

動かす 16 進の 1 桁と 4 ビット

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

0 0 0000
1 1 0001
9 9 1001
A 10 1010
B 11 1011
C 12 1100
D 13 1101
E 14 1110
F 15 1111

1 バイトの 8 ビットは、4 ビットが 2 つです。だから 1 バイトは 16 進数でちょうど 2 桁になります。10110010 は 1011 と 0010 に区切れ、1011 が B、0010 が 2 なので B2 です。すべてのビットが 1 の 11111111 は FF で、10 進数の 255 に当たります。Python では、16 進数であることを示すために頭に 0x を付け、0xFF と書きます。

16 進数を 10 進数に直すときは、左の桁から順に、それまでの合計に 16 を掛けて次の桁の値を足します。各桁に重み (右から 1、16、256) を掛けて足すのと同じ計算です。B2 なら、B の 11 に 16 を掛けて 176、2 を足して 178 です。

動かす 16 進から 10 進へ

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

B 11 11
2 2 178
178

1 行が 1 桁で、左から、桁の字、その桁の値、そこまでの合計です。最後の行の int(s, 16) も同じ 178 を返します。

8 進数は、0〜7 の 8 個の字で数を書く方法で、1 桁がちょうど 3 ビットに当たります。2 進数を右から 3 ビットずつ区切ると、そのまま 8 進数の桁になります。10110010 は 10、110、010 に区切れ、2、6、2 なので 262 です。Python では頭に 0o を付けて書きます。

動かす 8 進数は 3 ビットずつ

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

10110010
0o262
178

1 バイトの 8 ビットは 3 で割り切れないので、8 進数では桁の境目がバイトの境目と合いません。バイトを読むときに 16 進数がよく使われるのは、このためです。

下の図で桁の切り方を 16 進と 10 進で切り替えると、16 進では境目がビットの隙間にぴったり落ち、10 進ではビットの途中を通ります。2 進数と 16 進数を暗算で行き来できるのはこのためです。

16進数から10進数への変換

なぜ 16 進数を使うのか

16 進数を使うのは、2 進数を短く書けて、ビットの並びにすぐ戻せるからです。10110010 は B2 の 2 桁で済みます。10 進数の 178 も短いのですが、ビットの並びは見えません。

使う場面書き方の例16 進数にする理由
Web の色#RRGGBB赤、緑、青を 1 バイトずつ、2 桁ずつで書ける
メモリの番地0x で始まる英数字長い番号を、ビットの区切りのまま短く書ける
バイト列の表示b'\xff'1 バイトがいつも 2 桁になり、並べても読みやすい

CSS の色の #RRGGBB は、赤、緑、青の強さを、それぞれ 00 から ff (255) の 2 桁で書く決まりです。メモリの番地は、データを置いた場所の番号です。

動かして確かめる

変換の手順は、Python で 1 段ずつ動かすと確かめられます。まず 178 を 2 で割り続け、商と余りを 1 行ずつ出します。

動かす 2 で割って 2 進数にする

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

178 ÷ 2 = 89 余り 0
89 ÷ 2 = 44 余り 1
44 ÷ 2 = 22 余り 0
22 ÷ 2 = 11 余り 0
11 ÷ 2 = 5 余り 1
5 ÷ 2 = 2 余り 1
2 ÷ 2 = 1 余り 0
1 ÷ 2 = 0 余り 1
0b10110010

割り算は 8 回で、商が 0 になったところで止まります。余りを下の行から上へ読むと 1、0、1、1、0、0、1、0 で、10110010 です。最後の行の bin は、同じ並びに 0b を付けた 2 進数の文字列を返します。

次は逆向きです。1 が立っている桁の重みだけを出し、足し合わせます。

動かす 重みを足して 10 進数に戻す

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

1 の桁の重み 128
1 の桁の重み 32
1 の桁の重み 16
1 の桁の重み 2
合計 178
178 0xb2
178

1 の桁は 4 つで、重みの合計は 178 です。int(s, 2) は文字列を 2 進数として読み、同じ 178 を返します。hex は 16 進数の文字列 0xb2 を返しました。小文字ですが B2 と同じ値で、最後の行のとおり B2 を読むと 178 です。

最後に、色の #FF8000 を 2 桁ずつ切り、10 進数と 8 ビットの 2 進数に直します。

動かす 色を 1 バイトずつ読む

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

FF 255 11111111
80 128 10000000
00 0 00000000

赤が FF で 255、緑が 80 で 128、青が 00 で 0 です。赤は最大、緑は半分ほど、青は無しなので、橙色に見えます。どの行も、16 進数の 2 桁が 8 ビットにきれいに対応しています。

ビットの数と表せる通りの数も確かめます。

動かす n ビットで表せる通り

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

1 ビット 2 通り
4 ビット 16 通り
8 ビット 256 通り
16 ビット 65536 通り
32 ビット 4294967296 通り
8 ビット 0 〜 255
符号付き -128 〜 127
16 ビット -32768 〜 32767

n ビットで表せるのは 2 の n 乗通りです。8 ビットなら 256 通りで、0 も 1 通りとして使うので最大は 255 です。

符号付き (マイナスも表す) にすると、同じ 256 通りを半分ずつマイナスとプラスに分けて、−128〜127 になります。最後の行の 16 ビットの符号付きの範囲 −32768〜32767 は、あとの実例で使います。

決まった幅の器を超えると何が起きるか

値が器の幅を超えると、上の桁が捨てられて小さな値に化けるか、プログラムが止まります。どちらになるかは、器の作りと言語で違います。

Python の int はあふれない

Python の int (整数) は、大きさに上限がありません。公式の文書も、整数の精度に限りが無いと書いています。255 に 1 を足せば、そのまま 256 です。

8 ビットの器を Python で再現するには、& 0xFF (下の 8 ビットだけを残す計算) を使います。0xFF は 11111111 なので、それと重なる下の 8 ビット以外を 0 にします。

動かす 8 ビットの器で計算する

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

256
0
4
1267650600228229401496703205376

1 行目は int のままなので 256、2 行目は 8 ビットの器に入れた値で 0 です。256 は 2 進数で 100000000 の 9 桁になり、9 桁目の 1 が器からこぼれて、残った 8 桁がすべて 0 だからです。これを桁あふれ (オーバーフロー) と呼びます。3 行目の 250 + 10 も、器の中では 4 になります。4 行目のように、Python の int だけなら 2 の 100 乗でもそのまま出ます。

器の幅を決めると、止まる道具もある

値を決まった数のバイトに詰める道具は、範囲を超えると、こぼして化けさせる代わりにエラーで止まるものがあります。Python の int.to_bytes と struct がそうです。

動かす バイトに詰めるとき止まる

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

b'\xff'
OverflowError
int too big to convert
b'\xff'
struct.error
'h' format requires -32768
<= number <= 32767

(255).to_bytes(1, "big") は 255 を 1 バイトに詰め、中身が FF の 1 バイト b'\xff' を返します。256 を 1 バイトに詰めようとすると、OverflowError (値が大きすぎるという知らせ) で止まります。公式の文書は、決めたバイト数で表せない整数には OverflowError を出すと書いています。

struct は、値を決まった形のバイト列に詰める道具です。"B" は 1 バイトの符号なし、"h" は 2 バイト (16 ビット) の符号付きの形です。40000 は 16 ビットの符号付きの範囲を超えるので、struct.error で止まり、許される範囲 −32768〜32767 を知らせてきます。止まる道具はまだ親切な側で、黙って上の桁を捨てる器もあります。

同じ 8 ビットでも、読み方で値が変わる

同じビットの並びでも、符号なしとして読むか、符号付きとして読むかで値が変わります。符号付きの代表的な読み方が 2 の補数 (一番上の桁の重みをマイナスとして読むやり方) で、8 ビットなら一番上の桁を −128 として足します。

動かす 符号付きとして読む

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

b'\xc8'
200
-56
-128
b'\xff'

200 を詰めた 1 バイトは C8 です。符号なしで読めば 200、符号付きで読めば −56 になります。符号付きの 8 ビットで最大の 127 に 1 を足し、8 ビットの器に入れてから符号付きで読むと、−128 になりました。プラスの一番上からマイナスの一番下へ回り込んだわけです。最後の行のとおり、−1 を符号付きで詰めると FF です。

ビットの並びそのものには、マイナスかどうかの情報は入っていません。どう読むかは、器を決めた側の約束です。

反対に、マイナスの数を 2 の補数で作るときは、プラスの値のビットを全部反転し (0 と 1 を入れ替え)、1 を足します。−56 なら、56 の 00111000 を反転して 11000111、1 を足して 11001000 です。

動かす 反転して 1 を足す

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

00111000
11000111
11001000
0xc8
True

作った 11001000 は 16 進で C8 で、上で 200 を詰めた 1 バイトと同じ並びです。最後の行のとおり、Python に −56 を符号付きで詰めさせた 1 バイトとも一致します。~x は全部のビットを反転する演算で、& 0xFF で下の 8 ビットだけを残しています。

並び (8 ビット)16 進符号なし符号付き
11111111FF255−1
11001000C8200−56
1000000080128−128
011111117F127127

崩れる前提をまとめると、次の通りです。

  • 値は器の幅に入る、という前提。超えると、上の桁がこぼれて小さな値に化けるか、エラーで止まる
  • 書いた側と読む側が同じ読み方をする、という前提。符号なしと符号付きを取り違えると、200 が −56 に化ける
  • 足し算の結果も器に入る、という前提。255 も 1 もそれぞれは入るのに、足すと入らない

仕事でどう確かめるか

仕事では、値の範囲の端を試験で突き、器の幅を仕様で確かめます。

1 つ目は、境目の値で試すことです。8 ビットの値を扱う処理なら、0、1、127、128、255、256、−1 を入れたときにどうなるかを試験に書きます。境目のすぐ内側とすぐ外側を並べて試します。

2 つ目は、器の幅を仕様で確かめることです。データベースの列の型やファイルの形式には、何バイトで符号付きかが書いてあります。増え続ける数 (回数、時間、通し番号) は、何日動くと上限に届くかも見ておきます。

3 つ目は、手元の 1 行で変換を照らすことです。Python なら int("B2", 16) や hex(178) で済みます。頁の外で大きな数を変換するなら、16 進数の変換の道具で 10 進、2 進、8 進、16 進と 2 の補数を行き来できます。

関わる実例

決まった幅の器に入らない値は、ロケットと旅客機でも実際に問題を起こしています。

Ariane 5 の 501 便 (1996 年 6 月 4 日)

欧州のロケット Ariane 5 の最初の飛行は、1996 年 6 月 4 日、打ち上げの約 40 秒後に向きを外れて爆発しました。調査委員会の報告書によると、向きと速さを測る装置のソフトウェアで、64 ビットの浮動小数点の数を 16 ビットの符号付き整数に変換したとき、値が表せる大きさを超えました。これで Operand Error という例外が起き、装置が止まりました。

崩れた前提は「この値は 16 ビットに入る」です。報告書は、Ariane 5 は打ち上げの初めの水平方向の速さが先代の Ariane 4 よりかなり大きく、値が想定を超えたと書いています。似た変数の変換は守られていたのに、この変換は守られていませんでした。前の世代で入った値が、次の世代でも入るとは限りません。

Boeing 787 の発電機の制御装置 (2015 年)

米国の連邦航空局 (FAA) は 2015 年、Boeing 787 について耐空性改善命令 (飛行機の安全のために整備を命じる文書) AD 2015-09-07 を出しました。命令によると、電源を 248 日続けて入れたままにすると、発電機の制御装置の中の数え器があふれ、装置が停止の状態に入ります。4 台を同時に入れていれば 4 台が同時に止まり、交流の電源をすべて失うおそれがあります。

崩れた前提は「数え器は上限に届くほど長く動き続けない」です。命令は、製造元がソフトウェアを直すまでの暫定の手当てとして、120 日を超えない間隔で電源を切り直す整備を求めました。命令は数え器のビット数を書いていません。増え続ける数がいつ上限に届くかは、作る側が数えておく必要があります。

よくある問い

16 進数の A〜F は何を表すのですか

16 進数では 1 桁で 0 から 15 までを表すので、10 から 15 に 1 字の数字が足りません。そこで A を 10、B を 11、C を 12、D を 13、E を 14、F を 15 として使います。大文字と小文字のどちらで書いても同じ値です。

1 バイトは何ビットですか

1 バイトは 8 ビットです。8 ビットで表せるのは 256 通りで、符号なしなら 0〜255、2 の補数の符号付きなら −128〜127 です。16 進数ではちょうど 2 桁になり、00 から FF までで表します。

Python の int はあふれないのですか

Python の int は大きさに上限が無く、足し算や掛け算だけでは桁あふれしません。ただし、int.to_bytes や struct で決まった幅のバイトに詰めるとき、範囲を超えるとエラーで止まります。決まった幅の器を真似したいときは、& 0xFF のように下の桁だけを残します。

2 の補数とは何ですか

2 の補数は、マイナスの数をビットで表すやり方の 1 つで、一番上の桁の重みをマイナスとして読みます。8 ビットなら一番上の桁の重みが −128 になり、11111111 は −128 + 127 で −1 です。符号なしで読めば、同じ並びは 255 です。

確認クイズ

答えだと思う選択肢を押すと、その場で正誤と理由が開きます。4 問すべてに正しく答えると、この回は修了で、石が緑に変わります (この端末のブラウザに残ります)。間違えた問いは、あとから解き直せます。

1 問目

8 ビットの符号なしの器で表せる値の範囲はどれですか。

2 問目

2 進数の 10110010 を 16 進数で書いたものはどれですか。

3 問目

Python で (255 + 1) & 0xFF を計算すると、いくつになりますか。

4 問目

1 バイトの FF を、2 の補数の符号付きとして読むと、いくつになりますか。

説明課題

次のことを、自分の言葉で 3 行にまとめてください。書いたら、下の模範解答を開いて比べてください。

  • 8 ビットで表せる範囲を、符号なしと符号付きの両方で
  • その範囲を超えたときに何が起きるかを、Python の int との違いも含めて

模範解答

自分の説明を書いてから開いて、比べてください。

この回の先の一歩

色の指定、ログに出るバイト列、ビット演算の設定値など、16 進数と器の幅は画面とデータの両方の仕事で読み書きします。いまの自分が転職までの道のどの段にいるかは、転職診断で確かめられます。

もっと深く

この回の続きを、ゆめさくのコースの章や道具で深められます。頁の中の確認クイズに答えたあと、手を動かす量を増やしたいときに使ってください。

一次資料

どれも 2026年10月26日に開いて、題と中身を確かめました。

次へ

道 1 数と論理と計算量の回

  1. 1-12 進数と 16 進数桁の重み、変換、表せる範囲この回
  2. 1-2文字コードと文字化けUnicode、UTF-8、Shift_JIS、BOM頁で読む
  3. 1-3計算量を数えるBig-O、ループの回数頁で読む
  4. 1-4論理と真理値表AND、OR、NOT、ド・モルガン準備中
  5. 1-5リトルエンディアンとビッグエンディアンバイトの並び順、ネットワーク、ファイル頁で読む
  6. 1-6Base64 の仕組み64 字の表、= の詰め物、長さ 4/3頁で読む
  7. 1-7情報量とハフマン符号化ビット、確からしさ、圧縮頁で読む
  8. 1-8チューリングマシンと停止問題テープ、状態、計算できない問題頁で読む

道 1 の頁へ戻るほかの道を見る