CSSで色を指定するときに書く #ff5733 の 「ff」って、どうやって数字になるのか考えたことはありますか。 この「ff」は16進数で、10進数に直すと255——つまりRGBの赤の最大値です。 コンピュータの世界では10進数だけでなく、2進数・16進数が頻繁に顔を出します。 この記事では、なぜコンピュータは2進数で動くのか、16進数が使われる本当の理由、 そして手計算とJavaScriptでの変換方法を、カラーコード・IPアドレス・ファイルパーミッションなど 身近な実例を交えて解説します。
なぜコンピュータは2進数で動くのか
コンピュータの内部では、すべてのデータが0と1の2つの値で表現されています。 この2進数(binary)が選ばれた理由は、人間の都合ではなく物理の都合です。
電子回路において「電圧が高い/低い」という2つの状態は、ノイズや温度変化があっても 確実に区別できます。もし10進数を直接扱おうとすれば、10段階の電圧を正確に判別する必要があり、 少しの電気的な揺らぎで値が化けてしまいます。2状態しかない2進数なら、トランジスタのON/OFFという もっともシンプルなスイッチだけで論理演算を構成でき、信頼性が高く高速に動作します。
人間が10進数を使っているのは、単に指が10本あるから——それ以上の深い理由はありません。 10進数はコンピュータにとってむしろ不自然な数え方なのです。 一方で2進数は桁数がすぐに膨らむという欠点があります。 10進数の255はわずか3桁ですが、2進数では 11111111 と 8桁にもなります。これを人間が読み書きするのは現実的ではありません。そこで登場するのが16進数です。
16進数が使われる本当の理由
16進数(hexadecimal)が広く使われる理由は、2進数との変換が圧倒的に楽だからです。 16は2の4乗(2^4)なので、16進数1桁 = 2進数4桁という完璧な対応関係があります。
たとえば1バイト(8ビット = 2進数8桁)は、16進数ちょうど2桁で表せます。 2進数の 11111111 は16進数ではFF、10進数では255です。 これだけで桁数が4分の1になり、メモリダンプやカラーコードが一気に読みやすくなります。
もし10進数を使うと、2進数8桁は最大で10進数3桁(0〜255)になり、桁数が変わるうえに ビット単位での対応が崩れます。16進数なら上位4ビットと下位4ビットをそのまま別々に読めるため、 CPUレジスタやビットフラグを扱うエンジニアには欠かせない記法なのです。
10進・2進・16進の対応表
0〜16の値を3種類の基数で並べると、変換の規則がひと目で掴めます。
| 10進数 | 2進数 | 16進数 |
|---|---|---|
| 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 |
| 16 | 10000 | 10 |
注目したいのは10進数の10〜15が16進数ではA〜Fというアルファベットで表現される点です。 10進数でいう「10」は2桁になってしまい、1桁で15までを表したい16進数には使えないので、 続きの値をA・B・C・D・E・Fで埋めるわけです。そして16に達した瞬間、16進数も2桁目に繰り上がって10になります。
手計算で変換してみる
2進数 → 10進数
各桁に2の累乗を対応させて足すだけです。2進数の1011なら右から2^0・2^1・2^2・2^3の重みで、1×8 + 0×4 + 1×2 + 1×1 = 11(10進数)となります。
2進数: 1 0 1 1
重み: 8 4 2 1 (2^3 / 2^2 / 2^1 / 2^0)
計算: 8 + 0 + 2 + 1 = 11
10進数 → 2進数(2で割って余りを並べる)
10進数を2で割り続け、出てきた余りを下から読むと2進数になります。 13を例にすると以下のようになります。
13 ÷ 2 = 6 余り 1 ← 下位ビット
6 ÷ 2 = 3 余り 0
3 ÷ 2 = 1 余り 1
1 ÷ 2 = 0 余り 1 ← 上位ビット
余りを下から読むと 1101 → 13 = 1101(2)
10進数 → 16進数(16で割って余りを並べる)
方法は2進数と同じで、割る数を16にするだけです。余りが10以上ならA〜Fに変換します。 255を例にすると、255 ÷ 16 = 15 余り 15 → 15 ÷ 16 = 0 余り 15。 余りを下から読むと15・15なので、16進数では FF になります。
16進数と2進数の相互変換は、対応表を使って4ビットずつ置き換えるのが最速です。 2進数の 11010110 なら、 1101 → D、0110 → 6なので16進数では D6 です。
JavaScriptでの基数変換
JavaScriptなら toString(基数) とparseInt(文字列, 基数) で 2〜36までの任意の基数に相互変換できます。
// 10進数 → 2進数 / 16進数
(255).toString(2) // "11111111"
(255).toString(16) // "ff"
(255).toString(8) // "377"
// 2進数 / 16進数 → 10進数
parseInt('11111111', 2) // 255
parseInt('ff', 16) // 255
parseInt('0xff', 16) // 255(0xプレフィックス付きでもOK)
// 基数リテラル(そのまま数値として書ける)
0b11111111 // 255
0xff // 255
0o377 // 255(8進数)
// 0埋めで表示する(RGBカラーコード用)
const hex = (255).toString(16).padStart(2, '0') // "ff"注意点として、parseIntは必ず第2引数で基数を指定してください。省略すると環境によって解釈が変わる場合があり、 特に「0」から始まる文字列が8進数扱いされる歴史的な罠があります。 またtoString(16)は小文字を返すので、 大文字で出力したいときは .toUpperCase() を追加します。
実例で見る16進数と2進数
RGBカラーコード
CSSの #ff5733 は、 R=0xFF(255)・G=0x57(87)・B=0x33(51)を意味します。各色2桁ずつの16進数で0〜255の範囲を表現しており、 これは1バイト(8ビット)をちょうど16進数2桁で表せる性質を活用したものです。 色の細かい調整をしたいときは、色コード変換ツールでHEX・RGB・HSLを相互に見比べると直感的に理解できます。
IPv4アドレス
192.168.1.1 のような IPアドレスは、内部では32ビットの2進数です。これを1バイトずつ10進数にしてドットで区切っているだけで、 10進数表記の各数値(0〜255)は必ず1バイト分の情報量に収まります。 サブネットマスクを考えるときは2進数に戻すと理解しやすくなります。
Unicodeコードポイント
絵文字や日本語の文字は、Unicodeにおいて U+3042(あ)やU+1F600(😀)のように 16進数のコードポイントで識別されます。JavaScriptでは'あ'.codePointAt(0).toString(16)で取得できます。
ファイルパーミッション(chmod 755)
Linuxの chmod 755 の「755」は 8進数で、2進数の111 101 101に分解されます。3ビットずつ「所有者・グループ・その他」に対応し、 各ビットが「読み・書き・実行」を意味します。7 = 111は全権限、5 = 101は読み+実行というわけです。 8進数が現役で使われている数少ない実用シーンです。
基数変換を手軽に行うツール
手計算で全部やるのは大変なので、普段の開発では数値基数変換ツールを使うのがおすすめです。2進・8進・10進・16進を同時に表示するため、値を入れた瞬間に対応関係を確認できます。 デバッグ時にレジスタ値を読むときや、CSSカラーコードの計算にも便利です。
また、16進数はハッシュ値の表現にも使われます。SHA256の出力が64文字の16進数文字列になるのは、 256ビット(= 32バイト)を16進数2桁×32で表現しているためです。 ハッシュ値を生成したい場合は ハッシュ値生成ツールで実際の出力を確認してみてください。どちらのツールも処理はブラウザ内で完結し、入力値がサーバーに送信されることはありません。
まとめ
- コンピュータが2進数を使うのは、電子回路で2状態(電圧の高低)が最も安定して扱えるから
- 16進数1桁は2進数4桁に対応するため、1バイトを16進数2桁で簡潔に表せる
- 10進数→2進数・16進数は「割って余りを下から読む」手順で変換できる
- JavaScriptでは
toString(基数)とparseInt(文字列, 基数)で相互変換可能 - RGBカラーコード・IPアドレス・Unicode・chmodなど、身近なところに16進数と2進数が登場する
- 基数を同時表示したいときは 数値基数変換ツール が便利