コンピューターは0と1で情報を扱うと前に話しました。これを意識してプログラムを扱うときには、10進法では少し考えにくくなってしまいます。この章ではそんなときに便利な概念について話します。
では、今回の要点です。
では、いってみましょう。
さて、私たちは普段の生活で何の疑問もなしに10進数を使っています。(疑問を持って使っている人は、なかなか数学の素質があるかもしれませんね。)10進数とは、0〜9の10個の数字を使って表現された数のことです。数が無くなってしまう「9」の次は、桁をあげて「10」と表現するのですね。
しかし、同じような理屈を使えば、0〜2でも、0〜6でも数値を表現することができます。新しい数字を作れば、20進数でも100進数でも表現することができます。
そして、たとえ3進数で表現されていても、7進数で表現されていても、100進数で表現されていても、違う形であれ同じ数値を表現することが出来ます。(小数では循環小数になってしまうこともありますが。)そして、全ての表現は全く等価なのです。
では、先ずは考えやすい所から、0〜4の5個の数字を使った、5進数を考えてみましょう。
先ず、上の10進数の定義に、5進数用の条件を当てはめてみましょう。すると、「5進数とは、0〜4の5個の数字を使って表現された数のことです。数が無くなってしまう「4」の次は、桁をあげて「10」と表現します。」となることが分かります。これが5進数です。
では、実際に数を表現してみましょう。0の次は1です。1の次は2です。え? 当たり前だって? まぁ、我慢して下さい。
では、4の次はいくらになるのでしょうか? そうですね。10です。10の次は11で、11の次は12です。
そして、今度は14の次はいくらになるのでしょうか? そうですね。20です。では、44の次は? これは100になりますね。
何だかとても当たり前のことを書いてますね。そして、これを当たり前のことだと思えることが大事です。
では、5進数と10進数の2つを同時に考えてみましょう。紛らわしいので、5進数は(124)5のように、10進数は(124)10のように表現します。
小学校の時に、
219=100×2+10×1+1×9
というようなことをやった覚えがあります。当時は「そんな当たり前のことを何でいちいちするんだ」と思いましたが、これはn進数を理解するときに助けになります。
たとえば、(324)5を分解してみましょう。
(324)5=(100)5×3+(10)5×2+1×4
となりますね。(10)5とは、(4)5の次の数です。つまり、(5)10の事になります。(100)5は、(10)5×(10)5なので、(25)10になります。
よって、上の式は
(324)5=(25)10×3+(5)10×2+1×4
と書き換えることが出来ます。つまり、(324)5=(89)10になります。このようにすれば、5進数から10進数へ簡単に変換出来ることが分かります。
では、10進数から5進数を簡単に求める方法を考えてみましょう。
さて、何の疑問もなく
(324)5=(100)5×3+(10)5×2+1×4
という式を作りましたが、これは次のような手順をもって作ったとも考えられます。
先ず、(324)5÷(10)5を行います。すると、(32)5...(4)5になりますね。この余りが(1)5の位に当たります。
今度は次に、その時の商(32)5を(10)5で割ります。すると、商が(3)5になり、(2)5が余りになります。そして、この余りが今度は(10)5の位に当たります。
で、さらに、今度の商(3)5もついでに(10)5で割ると、商はもちろん0になり、余りは(3)5になります。この余りが(100)5の位に当たります。
(1)5の位、(10)5の位、(100)5の位というのは、このような計算から求められるのです。
「何を回りくどいことを」と思うかも知れませんが、こうやれば各位が求められることは分かるでしょう。
さて、ここからが本番です。ここで上の文の5進数で表記されている部分を10進数に直してみましょう。ただし、「(1)5の位」とかいう部分は除きます。すると、以下のようになります。
先ず、(89)10÷(5)10を行います。すると、(17)10...(4)10になりますね。この余りが(1)5の位に当たります。 今度は次に、その時の商(17)10を(5)10で割ります。すると、商が(3)10になり、(2)10が余りになります。そして、この余りが今度は(10)5の位に当たります。 で、さらに、今度の商(3)10もついでに(5)10で割ると、商はもちろん0になり、余りは(3)10になります。この余りが(100)5の位に当たります。 (1)5の位、(10)5の位、(100)5の位というのは、このような計算から求められるのです。 |
これが10進数から5進数を求める方法です。0〜4までは5進数でも10進数でも同じなので、上のことから(89)10=(324)5という事が分かりますね。
上では5進数を例にとって考えましたが、このことは何進数にでも適応できます。前者は進数の小さいものから大きいものへの変換、後者は進数の大きいものから小さいものへの変換にあたります。
ということで、いよいよ2進数と16進数の話に進みます。
「コンピューターは0と1を使って数値を表現している」と第21章で話しました。これは「0と1という2個の数字を使って数値を表現している」ことになるので、2進数です。つまり、上の文は「コンピューターは2進数を使って数値を表現している」と書き換えることが出来ます。
しかし、0と1だけで数値を表現すると、例えば(12345)10=(11000000111001)2となり、非常に長くなってしまいます。これでは人間にとってはあまり実用的ではないので、プログラムをするときは8進数か16進数を使います。
16進数は0〜9だけでは数字が足りないので、A〜Fの6個のアルファベットを「数字」と見なして使います。「0〜Fという16個の数字を使って数値を表現している」わけです。
(10)8=(1000)2で、(10)16=(10000)2です。つまり、8進数では2進数の3桁が丁度1桁に対応し、16進数では2進数の4桁が丁度1桁に対応します。
え? 唐突すぎるって? では、(10010101)2を例に取ってじっくり考えてみましょう。
では、先ず(10010101)2を8進数に直してみましょう。先にやった変換方法をちょっと変則的にした方法で直します。
さて、やはりここは分解です。(10010101)2は
(10010101)2=(1000000)2×(10)2+(1000)2×(010)2+(1)2×(101)2
のように分解できます。
さて、もう分かりましたね。(1000)2=(10)8と言いました。すると、(1000000)2=(100)8になります。(10)2=(2)8、(101)2=(5)8なので、上の式は
(10010101)2=(100)8×(2)8+(10)8×(2)8+(1)8×(5)8
となり、(10010101)2=(225)8となります。
これは、(10010101)2を3桁ずつ区切って(10:010:101)2とし、各ブロックを変換したのと同じ事になります。
16進数でも同じ事です。(10010101)2を4桁ずつ区切って(1001:0101)2とし、各ブロックを変換すると、(95)16となります。まぁ、各ブロックの変換はしなければなりませんが、10進数と比べるとずいぶん変換しやすいことが分かります。
C/C++言語では8進数と16進数を表現できます。8進数は頭に「0」をつけて、16進数は頭に「0x」を付けて表現します。16進数のA〜Fは大文字でも小文字でも構いません。
num = 214; // 10進数 num = 0326; // 8進数 num = 0xD6; // 16進数
ただ、残念ながら2進数は表現できません。8進数か16進数に直して表現しなければなりません。
また、8進数だと8桁の2進数、つまり1バイトの数値をブロックに分けると2桁:3桁:3桁という形になり、16進数だと4桁:4桁という綺麗な形になることが分かります。2,4バイトの数値になると8進数では1バイト目と2バイト目,2バイト目と3バイト目の間に区切りが来ません。ということで、プログラムでは主に16進数を使います。
ではこれを実際にどう活用するのか...は次回以降にまわして、今回はこのくらいで終わりにします。
では今回の要点です。
今回はかなり長くなってしまいました。次回はもう少し短くしたいと思いますが...。では、次回まで。
Last update was done on 1999.11.23
この講座の著作権はロベールが保有しています