前号: No 220 / 次号: No 222 / 一覧に戻る
コンピュータに関する話でしょっちゅう出てくるコトバの一つに 16進数というものがあります。 コンピュータが2進数で動いている、という話はどこかで聞いたと いう方も多いでしょう。ですがなんで16進数なのでしょうか? そもそも16という数字がワケわかりません。 2進数ならともかく、なんで16進数なんていう中途半端な進法が 使われるのでしょうか? 今回はこのナゾに迫ります。1. 16という値の意味
ネタを先に明かしておきます。 16進数というのは2進数の表記方法を改善しただけのもので、それ 以上の深い意味はありません。 2の4乗(=2進数で4ケタ分=4ビット)は16です。 つまり、2進数の4ケタ分を1ケタで表記できる方式なのです。 だったら、10進数でも良さそうなものですが、2進数→10進数は 非常に面倒です。 ですが、2進数←→16進数の変換は相互に簡単なルールで行えます から便利で良かったのです。 要は2進数での表記をラクにした方式が16進数表記というワケです。 言ってみれば、今回の解説はこれが全てなのですが、2進数自体が イマイチわからないという方も多いでしょうから、そこからいき ましょう。2. 2進数
10進数が10種類の数字(0〜9)を使って計算をします。 それに対し、2進数は2種類の数字(0と1)を使って計算をします。 10進数では10種類の文字が使えますから、0→1→2→3...→9まで 1ケタの数字で表現でき、9の次にケタ上がりが起きて、10となり ます。 ですが、2進数では2つの数字しかありませんから、0→1 しかあり ません。その次の値(10進数の2)はケタ上がりが起きて 10 と なります。 表形式にしてみましょう。 10進数 2進数 0 … 0 1 … 1 2 … 10 3 … 11 4 … 100 5 … 101 6 … 110 7 … 111 8 … 1000 9 … 1001 10 … 1010 なんとも妙な感じですが、2種類しか数字がないため、めった やたらとケタ数が増えていきます。 例えば、 1,000 … 1111101000 (10ケタ) 10,000 … 10011100010000 (14ケタ) 100,000 … 11000011010100000 (17ケタ) 1,000,000 … 11110100001001000000 (20ケタ) と、すごいペースでケタ数が増えていきます。 このようにやたらとケタ数が増えると書くのも読むのも大変です。 これを少しでもラクに扱えるようにと工夫したのが16進数なの です。3. 16進数
さて、問題の16進数です。 上述の通り、10進数は10種類の数字(0〜9)、2進数は2種類の 数字(0と1)を使います。 では16進数は? そりゃ、16種類の数字を使います。だから0〜....?ってあれ? 数字は16種類もないですよ。 現代人は10進数しか使いませんから、数字は10種類に決まって ます。 でも16進数を表記するには、何とかして16種類の文字を捻り出す 必要があります。 どうすれば良いのでしょうか? そこで無理矢理考案されたのが、文字をアルファベットで代用 する方式でした。0〜9の10種類に加えて、A〜Fの6種類の文字を 「数字」として使うわけです。 ですので、16進数と10進数の対応は次のようになります。 10進数 16進数 0 … 0 1 … 1 2 … 2 3 … 3 4 … 4 5 … 5 6 … 6 7 … 7 8 … 8 9 … 9 10 … A 11 … B 12 … C 13 … D 14 … E 15 … F 16 … 10 これもまた2進数と違う意味で不思議な表記です。10になっても ケタが変わらないというのは妙な感覚です。 16進数では2進数と逆に10進数よりも表記のケタ数が少なくなり ます。 例えば、5ケタの10進数の40,000を16進数で表記すると9C40と 4ケタで済んでしまいます。 ここで「ははぁ」と思い当たる方もおられるかもしれません。 例えば、Windows上でアプリが異常終了した時のエラーコード、 MACアドレス(ネットワークで使われる機器のIDのようなもの)、 電子証明書の指紋(フィンガープリント)などはいずれも16進数 で表記されています。4. 2進数←→16進数変換
最初に書いた通り、2進数と16進数は非常に簡単に相互変換ができ ます。 10進数 16進数 2進数 0 … 0 … 0 1 … 1 … 1 2 … 2 … 10 3 … 3 … 11 4 … 4 … 100 5 … 5 … 101 6 … 6 … 110 7 … 7 … 111 8 … 8 … 1000 9 … 9 … 1001 10 … A … 1010 11 … B … 1011 12 … C … 1100 13 … D … 1101 14 … E … 1110 15 … F … 1111 16 … 10 … 10000 注目していただきたいのは、最後の16のところです。 2進数と16進数が同時にケタ上がりしています。つまり、2進数の 4ケタ毎に16進数もケタ上がりするということです。 これは、2進数4ケタをそのまま16進数に置き換えられることを 示しています。 例えば、16ケタの2進数 を16進数に置換してみましょう。 (以下では見やすいように2進数の4ケタ毎に空白を入れています) 例1: 1010 1100 0101 0011 1010 1100 0101 0011 ↓ ↓ ↓ ↓ 1010 1100 101 11 ↓ ↓ ↓ ↓ A C 5 3 →16進数では、AC53となります。 例2: 1110 1100 1101 0011 (2箇所の0と1を変更) 1110 1100 1101 0011 ↓ ↓ ↓ ↓ 1010 1100 1101 11 ↓ ↓ ↓ ↓ E C D 3 →16進数では、ECD3となります。 この通り非常に単純な置換が可能です。 もちろん、16進数から2進数への変換も同様の手順で行えます。 ですが、10進数←→2進数の変換はこうはいきません。 1ケタづつ計算をするしかないのです。 つまり、こうなります。 例1: 1010 1100 0101 0011 これを10進数に直すには、次のような計算が必要になります。 1 * 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 + 0 * 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 + 1 * 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 + 0 * 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 + 1 * 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 + 1 * 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 + 0 * 2* 2* 2* 2* 2* 2* 2* 2* 2 + 0 * 2* 2* 2* 2* 2* 2* 2* 2 + 0 * 2* 2* 2* 2* 2* 2* 2 + 1 * 2* 2* 2* 2* 2* 2 + 0 * 2* 2* 2* 2* 2 + 1 * 2* 2* 2* 2 + 0 * 2* 2* 2 + 0 * 2* 2 + 1 * 2 + 1 = 44115 ものすごく複雑に見えますが、要は2進数の各ケタに2のn乗をかけた 計算を繰り返しているだけです。 各行の最初の1文字が変換元の2進数の値の1ケタにあたります。 (結果的に2進数を縦書きした形になっています) 16進数に比べて、明らかに面倒な計算が必要になることがわかる と思います。 実は2進数→10進数はまだ楽で、10進数→2進数変換ははるかに面倒 な計算が必要となります。 基本的には、2進数の全てのケタ(この例では16ケタ)が1か0かを 判断し、必要な計算をするという手順を繰り返すことになります。 ※以下の計算式は「求めるのが大変」なのを示すために書いたもの ですので、読み飛ばしていただいて問題ありません。 1) 44115 ≧ 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 か? を調べます。 この 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 というのは、 2進数では 1000 0000 0000 0000、10進数では 32768 となります。 なので、44115 ≧ 32768 かどうかを調べることになります。 結果はYesですから、 変換結果に 1000 0000 0000 0000 を加え、44115-32768=11347 を得て、 以降はその結果の11347を使います。 2) 11347 ≧ 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 か? を調べます。 今度は、2進数では 100 0000 0000 0000、10進数では 16384 です。 なので、11347 ≧ 16384 かどうかを調べることになります。 結果はNoですから、 そのケタ位置は2進数では0であることがわかります。 値がゼロですので、特に計算は行いません。 3) 11347 ≧ 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 りも大きいか? を調べます。 今度は、2進数では 10 0000 0000 0000、10進数では 8192 です。 なので、11347 ≧ 8192 かどうかを調べることになります。 結果はYesですから、 変換結果に 10 0000 0000 0000 を加え、1010 0000 0000 0000 とします。 また、11347-8192=3155 を得、以降はその結果の3155を使います。 4) 3155 ≧ 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 か? を調べます。 今度は、2進数では 1 0000 0000 0000、10進数では 4096 です。 なので、3155 ≧ 4096 かどうかを調べることになります。 結果はNoですから、 そのケタ位置は2進数では0であることがわかります。 値がゼロですので、特に計算は行いません。 5) 3155 ≧ 2* 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 か? を調べます。 今度は、2進数では 1000 0000 0000、10進数では 2048 です。 なので、3155 ≧ 2048 かどうかを調べることになります。 結果はYesですから、 変換結果に 1000 0000 0000 を加え、1010 1000 0000 0000 とします。 3155-2048=1107 を得、以降はその結果の1107を使います。 6) 1107 ≧ 2* 2* 2* 2* 2* 2* 2* 2* 2* 2 か?を 調べます。 今度は、2進数では 100 0000 0000、10進数では 1024 です。 なので、1107 ≧ 1024 かどうかを調べることになります。 結果はYesですから、 変換結果に 100 0000 0000 を加え、1010 1100 0000 0000 とします。 1107-1024=83 を得、以降はその結果の83を使います。 7) 83 ≧ 2* 2* 2* 2* 2* 2* 2* 2* 2 か?を調べ ます。 今度は、2進数では 10 0000 0000、10進数では 512 です。 なので、83 ≧ 512 かどうかを調べることになります。 結果はNoですから、 そのケタ位置は2進数では0であることがわかります。 値がゼロですので、特に計算は行いません。 8) 83 ≧ 2* 2* 2* 2* 2* 2* 2* 2 か?を調べます。 今度は、2進数では 1 0000 0000、10進数では 256 です。 なので、83 ≧ 256 かどうかを調べることになります。 結果はNoですから、上と同様で計算は不要です。 9) 83 ≧ 2* 2* 2* 2* 2* 2* 2 か?を調べます。 今度は、2進数では 1000 0000、10進数では 128 です。 なので、83 ≧ 128 かどうかを調べることになります。 結果はNoですから、上と同様で計算は不要です。 10) 83 ≧ 2* 2* 2* 2* 2* 2 か?を調べます。 今度は、2進数では 100 0000、10進数では 64 です。 なので、83 ≧ 64 かどうかを調べることになります。 結果はYesですから、 変換結果に 100 0000 を加え、1010 1100 0100 0000 とします。 83-64=19 を得、以降はその結果の19を使います。 11) 19 ≧ 2* 2* 2* 2* 2 か?を調べます。 今度は、2進数では 10 0000、10進数では 32 です。 なので、19 ≧ 32 かどうかを調べることになります。 結果はNoですから、計算は行いません。 12) 19 ≧ 2* 2* 2* 2 か?を調べます。 今度は、2進数では 1 0000、10進数では 16 です。 なので、19 ≧ 16 かどうかを調べることになります。 結果はYesですから、 変換結果に 1 0000 を加え、1010 1100 0101 0000 とします。 19-16=3 を得ます。 13) 3 ≧ 2* 2* 2 か?を調べます。 今度は、2進数では 1000、10進数では 8 です。 なので、3 ≧ 8 かどうかを調べることになります。 結果はNoですから、計算は行いません。 14) 3 ≧ 2* 2 か?を調べます。 今度は、2進数では 100、10進数では 4 です。 なので、3 ≧ 4 かどうかを調べることになります。 結果はNoですから、計算は行いません。 15) 3 ≧ 2 か?を調べます。 結果はYesですから、 変換結果に 10 を加え、1010 1100 0101 0010 とします。 3-2=1 を得ます。 16) 1 ≧ 1 か? なので2進数に 1 を加算。 変換結果に 1 を加え、1010 1100 0101 0011 とします。 1-1=0 となります。 これだけ手間をかけてやっと目的の 1010 1100 0101 0011 という 2進数を得ることができます。 こんなのはとてもやってられません。 だから、10進数で2進数の代用するというのは現実的でないのが わかります。5. 余談:8進数が使われた時代も...
この16進数というのは何も絶対的な基準などではなく、単に便利だ から使っているに過ぎません。 実際、かなり昔の話となりますが、1970年頃は16進数はほとんど 使われておらず、8進数がよく使われていたようです。(筆者も実際 に8進数を使われていた時代は全く知らず、古い資料で得た知識です) 8進数も16進数と目的は同じで、2進数表記の読みづらさを改善する ことが目的でした。 8進数が愛用されたのは、当時のCPUは12ビットや24ビットのものが 多く、最少の情報単位が6ビットとなっているものが多かったため です。 8進数は2進数3ケタ分(=3ビット)を1ケタで表記できますので、 6ビットの情報を表記するには丁度組具合が良く、2進数4ケタ分を 1ケタで表記する16進数よりも使い易かったのでしょう。 実際、1970年代に開発されたUNIXというOSには ファイル内容を 8進数で表示してくれる od (Octal dump:8進数出力)という コマンドがありました。現在も使えるのですが、主として16進数 変換に利用されています。 今となっては、odコマンドの語源を知らない人も多いことでしょう。 こういった点でも時代の流れを感じられるのは面白い話です。6. まとめ
16進数という表記がコンピュータ関連では多用されています。 コンピュータは2進数で動作しているのですが、2進数をそのまま 書くと非常に長くなってしまいます。 それを簡便に扱えるようにするため、2進数4ケタを1ケタで表記 できる16進数が多用されるようになっています。 実際、16進数と2進数の相互変換は計算なしででき非常に簡単です。 一方、10進数と2進数の相互変換は計算が必要となり、かなり面倒 で、簡単とは言えません。 もっとも、16進数が利用され始めたのはせいぜい1970年代後半の 話で、それ以前は8進数が多用されていたようです。 (当時は2進数をそのまま使っているケースも多かったようです) 今回はお盆明けなので、軽目の話題を短かい目に、と思ったのです が、メルマガ史上、最長(本文が400行越え)になってしまいました。 「わかった!」と思っていただければ、とても嬉しいです。 次回もお楽しみに。