前の章では「コンピューターは0〜一定値以内の整数しかわからない」ということを説明しました。
これを見て当然みなさんは疑問に思うでしょう。例えばエクセルのような表計算ソフトでは3.14とか-234とかいろいろ扱えます。これは一体どうやっているのでしょう?
ここではそういった数がどのように表現されるのかを解説します。
大きな整数
昔の8ビットCPUでは一度に0〜255までの数しか扱えませんでした。これでは実際の問題に対してはほとんど役に立たないのは当然です。最新のものでも42億前後です。これは結構大きいとは言っても、現在の世界人口を考えれば、あまり多くはありません。
では例えば0〜255しか扱えないCPUでどうやってそれ以上の数を扱うのでしょう?
答えは簡単です。2回とか4回に分けて計算するのです。
すなわち1110101111101000という数があったとしたら、これを8桁ずつに分けて別々に計算すればいいのです。
よくわからない?原理は下の通りです。
小学校で足し算をするとき
1 1 ←繰り上がりがあるとき1を加えましたね
1578
+2348
──────
3926
|
としませんでしたか?この計算の途中でできなければいけないのは一桁の足し算だけです。しかしそれにも関わらず、どんな大きな数の足し算でもできるわけです。
2進法の場合も同様で、1桁の2進法の足し算ができれば、原理的に何桁の足し算もできるわけです。しかし1桁ではあまりにもちゃちなので、例えば8ビットのCPUでは8桁いっぺんに計算ができます。
というわけでその気になればメモリーのエリアの許す限りの大きな数を扱えます。
しかし実際は2回に分けて0〜65535までとか、4回に分けて0〜4294967295という範囲の計算しかしません。その理由は実際上はこの程度で十分なことが多いことと、次の章で述べる、負の数の問題があるからです。
負の数の表し方
さてその気になれば大きな数が扱えることはわかりましたが、それでは負の数はどうでしょう?
光あるところに陰があるように、収入があれば支出もあります。
マイナスを表すには通常は数の前に−記号をつけます。
ところが前にも書いたとおり、コンピューターは0〜一定数の正の整数しか理解できません。マイナス記号なんてないんです!
それでは一体どうやってマイナスの数を表現するのでしょう??これは結構おもしろい問題です。
ところでマイナスの数とは以下のように定義できることがわかると思います。
あるxという数にyという数を足したとき答えが0になれば、yは−xである。
すなわち、−xとはxに足すと答えが0になるような数である。
つまり x+y=0 → −x=y
例えば 10+y=0 → −10=y
|
まあ当たり前ですね。
ここでうまいことを考えた人がいました。コンピューターが一定範囲の数しか扱えないことを逆利用するのです。
前に8ビットのCPUは0〜255までしか扱えないと言いました。もっと上等な物でも、上限があるのは同じです。
それでは8ビットCPUの例として、255+1の結果はどうなるでしょう?
答えは当然256ですが、これはこのCPUの扱える数ではありません。しかしそれでもCPUは強引に計算をします。その結果は0になってしまうのです。
どうしてでしょう?
これは次のように考えると何となくわかるでしょう。
例えば9999+1=10000ですが、計算している紙の左に余白がなくて繰り上がった分の1が書けなくなってしまったと思ってください。すると答えは0000です。
要するにコンピューターで計算した結果が使える数の範囲内にないときは、はみ出した分はどこかに行ってしまって、下の桁の結果だけが戻ってくるのです。
256は2進法で表せば100000000です。その下8桁は00000000になります。
ともかくこうやって戻ってきた0と正真正銘の0は全然区別がつかないのです(もちろん計算結果が桁あふれしたということは分かりますが、結果だけを見ても分からないし、そこで壊れてしまったりもしません)
それでマイナスの話ですが、その人は考えたわけです。
255+1=0 になってしまう。
ならば、255=−1と考えて何が悪い?
同じように
254+2=0 だから 254=−2
253+3=0 だから 253=−3
252+4=0 だから 252=−4
・・・・
うまい!というか騙されたというか・・・ともかくこうやってマイナスを定義するのです!!
それはそうと上の式を続けていくと
127+129=0 だから 129=−127
128+128=0 だから 128=−128
129+127=0 だから 127=−129・・・?
ということになって重なってしまいます。そこでコンピューターで負の数を扱いたいときは、0〜255まで扱えるCPUでは−128〜127の範囲の数ということになります。
これは前項のようにもっと大きな数でも同じように定義できます。
このためよく入力できる数値の範囲が
-32,768 〜 32,767
-2,147,483,648 〜 2,147,483,647
などという変な数字になっているのを見たことはありませんか?これはコンピューターの内部でマイナスの数がこのように表現されているために他ならないためです。
ちなみにこのマイナスの定義方法は、数に上限があって、その上限を越えたら0になるという性質を利用しています。前章の大きな数の問題では、その気になればいくらでも大きな数を計算できると言いました。足りなくなったら次々に分割数を増やしていけばいいからです。しかしこのやり方で上のマイナスの定義をするのは難しいことはわかるでしょう。というわけで、実際上でもコンピューターの扱える数の範囲には制限が必要になってくるのです。
実数の表し方
さて数は整数だけではありません。一般的には3.141592とか1/3といった小数や分数が使われます。
これはどうやって定義するのでしょう。
まず基本的に、無限小数の使用はできません。また分数もよっぽど特別なことをしないと使えません。
コンピューターが扱えるのは基本的に有限小数と浮動小数点数なのです。
「有限小数」はわかりやすいですね。3.1416とかいった数です。これを表現するためには例えば整数の下4桁は小数点以下である、とかいうような適当な決まりを作り、それに基づいて計算すればいいのです。
この決まりに従えば3.1416は31416という数で表せます。足し算や引き算ならばそのままで問題ありません。
かけ算の時はかけた結果を10000で割ってやればいいのです。どうしてかって?それは小数のかけ算を習った時を思い出してください。小数点にかまわずにかけ算を行ってしまってから、後から小数点の位置をつけましたね?まあそんな理由です。
それでは「浮動小数点数」とはなんでしょう。
上記の有限小数のやり方をこの世界では「固定小数点数」といいます。これはわかりやすいのはいいのですが、すごく狭い範囲の数しか扱えません。ところが実際の計算では0.00000000000000000000000001とか1000000000000000000000000000000000000とかいった数を同時に扱わなければならないこともよくあります。そうなると固定小数点のやり方ではすぐに値がはみだしてしまいます。
しかしたとえば1283782387238758612874623とかいう数値を扱う場合、ほとんどの場合は本当に必要なのは最初の数桁です。最後の一桁まで厳密に計算しなければならないような状況は稀です。
このため以下のような数の表記があったとしても実用上はほとんど差し支えないでしょう。すなわち、
最初の10桁は1526843215である。
全体の桁数は20桁である。
|
こういう発想の元に生まれた表記法が「浮動小数点」です。
物理や化学の教科書にはよく以下のような記述が出てきます。
実は浮動小数点数とは要するにこれです。
電卓などを使って大きな数を計算するといきなり .2345e24などという表記になったことがあるでしょう。これは
0.2345×1024 = 234500000000000000000000
|
のことです。
この数は最初の0.2345という部分(仮数部)と後の24という部分(指数部)を別々に保存します。
こういうルールであれば計算できるのは分かると思います。どうやって計算するかって?まあそれぐらいは昔の教科書でも引っぱり出してください。そもそも知らなくても特に悪いことは起こりません。
コンピューターの数は正確ではない・・・こともある
以上のようにコンピューターの内部では数値が表されます。ここまで読んでもらえば、コンピューターの計算が絶対正しいということはあり得ないことが分かるでしょう。
なぜなら整数を扱っていれば上限や下限の値があります。それをはみ出したらもうなんだか分からないことになります。
実数を扱っていれば、例えば1/3という値を正確に表すこともできません。
しかしもう一つ大きな落とし穴があります。
それはコンピューターが2進法であるということです。
例えば1/5という数があります。これは十進法では0.2という有限小数になります。しかしコンピューターの内部ではどうなっているのでしょう?
当然のことながら、二進法の小数とは小数点以下も2進法です。その結果として、2進法では分母が2の累乗である形の分数以外は、すべて循環小数となってしまいます。
すなわち分母が2nの形の分数のみが2進法では有限小数となります。
ここで1/5はどうでしょう?5は2の累乗ではありません。従って2進法の小数では以下のようになってしまいます。
分数では | 2進法小数では |
1/2 | 0.1 |
1/4 | 0.01 |
1/8 | 0.001 |
3/4 | 0.11 |
1/5 | 0.0011001100110011.... |
もちろんこれを無限に続けるわけにはいきませんから、どこかで打ち切ってしまわなければなりません。
すなわち、10進法では問題なく割り切れて有限小数になるはずの数でも、コンピューターで計算するとそうはならないことがあるのです。
これを丸め誤差といいます。
といっても、実際にはあまり気にする必要はありません。ただ厳密な計算が必要な場合は、このことは必ず注意しなければならない問題です。
要するにみなさんの場合は、
必ずしもコンピューターの数は正確ではない・・・ことがある
ということだけ覚えておけばいいです。
これだけでも結構怖い話ですけどね。
|