2進・8進・16進:プログラミングで各基数が使われる理由

約4分

10 進数は人間にとって自然ですが、コンピュータの世界では 2 進・8 進・16 進が頻出します。なぜ複数の基数が共存しているのか、各基数の使い分けを整理します。

各基数の表記法

基数名称使う数字例(10進の 255)プレフィックス
22進 (binary)0, 1111111110b
88進 (octal)0-73770o、または 0
1010進 (decimal)0-9255(なし)
1616進 (hexadecimal)0-9, A-FFF0x

JavaScript では 0b111111110o3772550xff がすべて等しい。

2 のべき乗との対応

コンピュータの世界で各基数が使われる理由は、ビットとの対応の良さです:

  • 2 進:1 桁 = 1 bit
  • 8 進:1 桁 = 3 bit(2³)
  • 16 進:1 桁 = 4 bit(2⁴)

10 進は 2 のべき乗ではないので、ビットと対応しません。「255 = 1111 1111」のような変換は手計算が大変。一方、16 進なら 0xFF = 1111 1111 で 1 文字 = 4 bit。ビット列を簡潔に表すには 16 進が圧倒的に便利です。

なぜ 16 進が主流か

8 進と 16 進、どちらも 2 進と相性が良いですが、現代では 16 進が主流です。理由:

  • バイト(8 bit)との対応:1 バイトを 16 進 2 桁で表せる(00〜FF)
  • アラインメントが綺麗:32 bit = 8 桁、64 bit = 16 桁
  • 読みやすい:3 桁の 8 進よりバイト境界が明確

8 進は Unix の chmod(chmod 755)など歴史的な場面で残っているが、新規実装ではほぼ 16 進。

相互変換のコツ

2 進 → 16 進

4 bit ずつまとめて 16 進にする:

1111 1111 → F F → FF
1010 1100 → A C → AC

逆も同じく、16 進 1 桁を 4 bit に展開。

10 進 → 2 進

2 で割って余りを並べる(下位ビットから):

13 ÷ 2 = 6 余り 1
6 ÷ 2 = 3 余り 0
3 ÷ 2 = 1 余り 1
1 ÷ 2 = 0 余り 1
→ 1101

または「2 のべき乗の引き算」:13 = 8 + 4 + 1 = 1101

10 進 → 16 進

16 で割って余りを並べる、または 4 bit ずつ 16 進化。

実装で 16 進が出てくる場面

  • 色コード#FF8C42(RGB 各 8 bit を 2 桁の 16 進で表示)
  • メモリアドレス0x7ffe0a3f...
  • バイナリダンプhexdumpxxd
  • ハッシュ値:SHA-256 の 64 桁の 16 進
  • UTF-8 エンコード%E3%81%82E3 81 82 は 16 進バイト
  • MAC アドレス00:1A:2B:3C:4D:5E

8 進の今の用途

  • chmod 権限chmod 755 の 7、5、5 はそれぞれ rwx を 3 bit ビットマスクで表現
  • 古いプログラミング言語の文字コード:C 言語の \033 は ESC 文字
  • Linux の umask

新規開発で 8 進を選ぶ理由は少なく、レガシーシステムや既存規約に従うために使う形です。

言語による表記の違い

JavaScript:  0b1111, 0o17, 0xF
Python:      0b1111, 0o17, 0xF
Ruby:        0b1111, 0o17, 0xF
C:           0b1111 (C23以降), 017, 0xF
Java:        0b1111, 017, 0xF
Rust:        0b1111, 0o17, 0xF

C の伝統的な「先頭 0 だけで 8 進」(017 = 15)は誤解を招きやすく、新しい言語は明示的な 0o プレフィックスを採用しています。

まとめ

  • 2 進・16 進はビット表現と相性が良いから使う
  • 16 進が主流(バイト境界が綺麗、可読性が高い)
  • 8 進は chmod など歴史的な場面で残る
  • 相互変換は「4 bit ↔ 16 進 1 桁」を覚えれば楽

異なる基数間の変換を試したいときは、本サイトの基数変換ツールが手早いです。10 進・2 進・8 進・16 進を相互に変換できます。