16 進数から 10 進数への変換
16 進数から 10 進数への変換
このレッスンで分かること
- プログラムを書いていると 16 進数 (hexadecimal、略して hex) が頻繁に出てきます
- なぜわざわざ 16 進数を使うのでしょうか
- 16 進数は
0-9に加えてA-F(またはa-f) を桁として使います
16 進数から 10 進数への変換 とは
16 進数 (hexadecimal) の文字列を 10 進数の整数に変換する関数を実装し、4 ビット = 1 桁の関係を理解する。
プログラムを書いていると 16 進数 (hexadecimal、略して hex) が頻繁に出てきます。CSS のカラーコード #FF6600、メモリアドレス 0x7FFE0000、エンコーディングの \xFF、ハッシュ値の a3f5... など、技術文書には 16 進数があふれています。
なぜわざわざ 16 進数を使うのでしょうか。それは 4 ビット = 1 桁 という美しい対応があるからです。1 バイト (8 ビット) はちょうど 2 桁の 16 進数で表せて、視認性が抜群です。
16 進数は「4 ビットをまとめて 1 文字にする」記法。2 進数の桁数(文字数)を 1/4 に短縮できる。
16 進数の桁
16 進数は 0-9 に加えて A-F (または a-f) を桁として使います。
| hex | dec | binary |
|---|---|---|
| 0 | 0 | 0000 |
| 1 | 1 | 0001 |
| 9 | 9 | 1001 |
| A | 10 | 1010 |
| F | 15 | 1111 |
たとえば "FF" は 10 進数で 15 * 16 + 15 = 255 であり、これは 1 バイトで表せる最大値です。"FF6600" のような CSS カラーコードは、上から R = FF = 255、G = 66 = 102、B = 00 = 0 の RGB 値が並んでいる、と読み解けます。
CSS の
#FF6600はR = 255、G = 102、B = 0。ビビッドなオレンジ色になる。
変換アルゴリズム
16 進数を 10 進数にするには、2 進数の場合と同じく 桁の重み付き和 を計算します。重みは 16^0、16^1、16^2 …。
例: "1A3" を 10 進数にする。
1 * 16^2 = 256A * 16^1 = 10 * 16 = 1603 * 16^0 = 3- 合計:
256 + 160 + 3 = 419
アルゴリズムとしては、左から 1 文字ずつ読みながら result = result * 16 + 桁の値 を繰り返します (ホーナー法)。桁の値 は 0-9 か A-F を見て対応する整数に変換します。
Python での実装
Python
def hexToDec(hex_str):
result = 0
for ch in hex_str.upper():
if '0' <= ch <= '9':
digit = ord(ch) - ord('0')
elif 'A' <= ch <= 'F':
digit = ord(ch) - ord('A') + 10
else:
continue
result = result * 16 + digit
return resultポイントを 3 つ整理します。
hex_str.upper()で大文字小文字を統一しておくと処理が楽0-9はord(ch) - ord('0')で数値に変換A-Fはord(ch) - ord('A') + 10で10-15に変換
JavaScript での実装
JavaScript
function hexToDec(hexStr) {
let result = 0;
for (const ch of hexStr.toUpperCase()) {
let digit;
if (ch >= '0' && ch <= '9') {
digit = ch.charCodeAt(0) - '0'.charCodeAt(0);
} else if (ch >= 'A' && ch <= 'F') {
digit = ch.charCodeAt(0) - 'A'.charCodeAt(0) + 10;
} else {
continue;
}
result = result * 16 + digit;
}
return result;
}charCodeAt(0) で文字コードを取り出して引き算します。Python の ord() と同じ役割です。
2 進数との橋渡し
16 進数の本当のうま味は、2 進数との変換が暗算でできる こと。F = 1111、A = 1010 のように 4 ビット単位で覚えればよく、0xFF6600 は瞬時に 11111111_01100110_00000000 と読めます。逆方向も同様で、10110010 なら 1011 0010 = B2 です。CPU のレジスタやメモリダンプを読むとき、この感覚は強力な武器になります。
プログラマがプロを名乗るには
0xA = 1010、0xF = 1111くらいは暗算できると良い。
よくある間違い
1 つ目は 大文字小文字の混在 を考慮し忘れること。"ff" も "FF" も "Ff" も同じ 255 ですから、必ず upper() か lower() で統一しましょう。2 つ目は 0x プレフィックス の扱いです。"0x1A3" のように先頭に 0x が付くケースがあります。本問題では付かない前提ですが、実務では startswith("0x") を見て切り落とす処理が必要です。3 つ目は chr と ord の混同です。ord('A') は 65 を返しますが、chr(65) は 'A' を返します (逆向き)。
やってみよう
hexToDec("FF")が255になる。hexToDec("100")が256になる。hexToDec("DEADBEEF")が3735928559になる。これは伝統的にメモリ未初期化のマーカーとして使われる値。hexToDec("CAFEBABE")が3405691582。これは Java の.classファイルの先頭 4 バイトのマジックナンバー。hexToDec("FACEFEED")hexToDec("BEEFDEAD")なども有名な hex 文字列。試して結果を見てみよう。
16 進数を扱えるようになると、メモリダンプ、ネットワークパケット、暗号、ファイルフォーマットの世界が一気に身近になります。
よくある質問
Q. 進数変換はなぜプログラミングで必要なのですか?
A. コンピュータは内部で 2 進数を扱うため、ビット演算やメモリ操作で 2 進・16 進の理解が必須です。色コード(#FF8800)、ファイル権限(0755)、IP アドレスのサブネット計算など、実務でも進数変換に触れる機会は多くあります。
Q. 10 進数を 2 進数に変換するアルゴリズムは?
A. 数を 2 で割り続け、余りを下から並べると 2 進表現になります。例えば 13 → 6 余 1 → 3 余 0 → 1 余 1 → 0 余 1 で 1101 です。多くの言語は bin() / Integer.toBinaryString() などの組み込みがあるため、それを使うのが安全です。
Q. Base64 はなぜ 4/3 倍に膨らむのですか?
A. 3 バイト(24 ビット)を 4 文字(各 6 ビット)に変換するため、データ量が 4/3 倍になります。8 ビット境界の任意バイト列を ASCII 印字可能文字だけで安全に運ぶための仕組みで、メール添付や URL 内のバイナリ埋め込みで使われます。
次のレッスン
次は 第 1 章まとめクイズ に進みましょう。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- 16 進数変換 の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. 16 進数変換 とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
要件
- 0-9、A-F、a-f のみからなる文字列と仮定して良い (0x プレフィックスはない)
- 組み込みの基数変換 (int(s, 16) / parseInt(s, 16) / Integer.parseInt(s, 16)) は使わない
- 大文字小文字どちらも処理できること
入出力例
test-cases.txt
hexToDec("FF") → 255
hexToDec("0") → 0
hexToDec("1A3") → 419
hexToDec("ff") → 255
hexToDec("100") → 256
hexToDec("ABCDEF") → 11259375
hexToDec("10") → 16