Dev Study
← コンピュータの仕組み
レッスン 2 / 13·約 12 分·第1期 コンピュータ単体の仕組み

2進数 — オンとオフの並びで、なぜ数が表せるのか

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理今ここ
  7. DB保存

前回、コンピュータは0と1しか区別できないと確認しました。今回はその0と1の並びが、どうやって数や文字になるのかを見ます。

まず結論

2進数は特別な数ではありません。私たちが使う10進数と、桁が繰り上がるタイミングが違うだけです。

ビット数が決まると、表せる値の範囲が決まります。8ビットなら0〜255の256通り。この「範囲の上限」が、後で出てくる桁あふれやIPアドレスの理解に直結します。

? 読む前に予測

8ビット(0と1が8個)で表せる値は、全部で何通りでしょうか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

2進数は、繰り上がるタイミングが違うだけ

「2進数」と聞くと身構えてしまいますが、仕組みは私たちが毎日使っている10進数と全く同じです。違うのは、いくつで桁が繰り上がるかだけです。

10進数では、0から数えて9の次で桁が繰り上がり10になります。使える記号が0〜9の10種類だからです。2進数では、使える記号が0と1の2種類しかないので、1の次で桁が繰り上がって10(イチゼロ)になります。

各桁の「重み」も同じ考え方です。10進数の 253 は、2×100 + 5×10 + 3×1 です。右から1, 10, 100と10倍ずつ増えます。2進数では右から 1, 2, 4, 8, 16 と2倍ずつ増えます。

具体実物

実際に数えてみる

2進数の各桁の重みを書き出すと、変換は足し算になります。

2進数 1101 を10進数に変換する表
桁の重み 8 4 2 1
ビット 1 1 0 1
↓ ↓ ↓ ↓
計算 8 + 4 + 0 + 1 = 13

重みが1のところだけ足す、それだけです。いくつか並べてみます。

10進数と2進数の対応(実際に計算して確認済み)表
10進数 2進数 必要なビット数
0 0 1
1 1 1
2 10 2
5 101 3
9 1001 4
13 1101 4
255 11111111 8
256 100000000 9

255 と 256 の間で、必要なビット数が8から9に増えていることに注目してください。ここが次の話につながります。

✓ ここまでの確認

2進数の 101 は10進数でいくつですか。

抽象原理

ビット数が決まると、上限が決まる

ここが実務に直結する一番大事な点です。使えるビット数を決めた瞬間に、表せる値の上限が決まります。

1ビットなら2通り。2ビットなら4通り。ビットが1つ増えるたびに、表せる値の数は2倍になります。8ビットなら2を8回かけて256通り、つまり0〜255です。

そして、その範囲を超える計算をするとどうなるか。収まらなかった上の桁は、単純に捨てられます。

4ビットで 13 + 9 を計算すると
110113○ 4ビットに収まる
+ 10019○ 4ビットに収まる
= 1011022 — 5ビット必要× 収まらない
0110上位1ビットが捨てられた結果○ 6 になってしまう
↓
13 + 9 の答えが 6 になる — これが桁あふれ(オーバーフロー)
  • ・多くの言語・CPUの整数演算では、エラーにならず静かに間違った値が出るのが厄介なところ
  • ・「なぜか数値がおかしい」系の不具合の典型的な原因

エラーで止まってくれれば気づけますが、多くの場合静かに間違った値が出ます。これが桁あふれの怖さです。

具体実物

文字も同じ仕組みで表す

数が表せるようになったら、文字は簡単です。「このビット列はこの文字」という対応表を決めるだけです。

ASCIIの一部(RFC 20 で定められた対応)表
文字 10進数 2進数
A 65 01000001
B 66 01000010
a 97 01100001
0 48 00110000
スペース 32 00100000

ここで重要なのは、01000001 というビット列そのものには「文字」という情報が入っていないことです。同じビット列を、数値の65として扱うこともできれば、文字のAとして扱うこともできます。どちらとして読むかは、プログラムが決めています。

✓ ここまでの確認

文字化けが起きるのは、なぜでしょうか。

⇄ 2つを見比べる
具体例 A

4ビットの足し算

13 + 9 = 22 は5ビット必要ですが、4ビットしかないので上の桁が捨てられ、6 になります。エラーは出ません。

桁あふれ表
1101 (13)
+ 1001 ( 9)
------
10110 (22) ← 5ビット
0110 ( 6) ← 上位が捨てられた結果
具体例 B

IPv4アドレスの枯渇

IPv4アドレスは32ビットなので、表せる数は約43億個が上限です。世界中の機器がこれを超えたとき、後から桁を増やすことはできませんでした。

32ビットの上限表
32ビット = 2の32乗 = 4,294,967,296 個
 
世界の人口・機器数がこれを超えた
→ 桁を増やせないので IPv6(128ビット)を
新しく作るしかなかった

4ビットの足し算と、IPv4アドレスの枯渇。規模は全く違いますが、同じ原理が働いています。それは何でしょうか。

どちらも「最初に決めた桁数」が後から効いてきます。

この章のまとめ

  • 2進数は10進数と同じ仕組み。繰り上がるタイミングと桁の重み(2倍ずつ)が違うだけ。
  • ビット数を決めると表せる値の上限が決まる。8ビット=256通り(0〜255)。
  • 上限を超えると桁あふれが起き、多くの言語・CPUの整数演算ではエラーにならずに静かに間違った値になる。
  • 文字はビット列と文字の対応表(文字コード)で表す。ビット列自体に「文字」という情報は無い。
  • 文字化けはビットの破損ではなく、解釈するルールのずれ。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

環境:

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 4正解: 0

2進数の 1101 は、10進数でいくつですか。

用語集(4語)
2進数
0と1だけで数を表す方法。桁が2で繰り上がる。各桁の重みは右から1,2,4,8,16…と2倍ずつ増える。
バイト (byte)
8ビットをひとまとめにした単位。0〜255の256通りを表せる。ファイルサイズやメモリ容量の基準単位。
桁あふれ (オーバーフロー)
決められたビット数に収まらない値になること。上位の桁が捨てられ、予想外の値になる。プログラムの不具合の典型的な原因のひとつ。
文字コード
どのビット列をどの文字に対応させるかの取り決め。ASCIIやUTF-8など。送る側と受け取る側でこの取り決めが違うと文字化けが起きる。