前回は、2進数を使って小数を計算すると「誤差」という問題が起こるということをご説明しました。
誤差は、気にしなくていい場面も数多くありますが、状況によっては無視できないこともまた同様に数多くあります。ご存知の方もいらっしゃると思いますが、ここでひとつの例をご紹介しましょう。
コンピュータに何かをさせようとする場合、誤差は常に意識しなければいけません。たとえば、「0.1を順次足していき、合計が1になったら終了しろ」というプログラムを作ろうとした場合、一般的には次のような手順を書くことになると思います。
1: 変数xに、ゼロを代入(x=0)
2: プログラムの繰り返し点:
3: 変数x自身に0.1を加算(x=x+0.1)
4: 変数xの値を検査し、
1でなければ“プログラムの繰り返し点”に戻る
(1であれば、次のステップがないので終了する)
普通なら、0.1を10回加算すれば1になりますから、このプログラムはちょうど10回目の加算を終えた直後で終了するはずです。でも、このとき、コンピュータ内部で0.1が本当に0.1でなかったらどうなるでしょうか。たぶん、加算結果が1になることはないでしょうから、このプログラムは永遠に終わりません。
そんな馬鹿な、と思われるかもしれません。でも、ここで前回の話を少し思い出してみてください。0.1を2進数に変換すると0.0001100110011……というように、循環小数となってしまいます。コンピュータは無限の数を扱うことはできないためどこかで調整をすることになりますが、一般にはある桁で切り捨てが使われるので、実際には0.1よりもわずかに小さい値となります。極論すれば、10進数の0.1は、2進数となった時点で10進数の0.09999999999……という数に近い値となるわけです。
実際には、0.9999999999……は近似値で1となりますので極端に神経質になる必要はありませんが、先ほどのプログラムに当てはめると、0.09999999999……を10回加算した結果は0.9999999999……ですから1ではありませんよね。で、11回目の加算をした結果は1.0999999999……ですから、ちょうど1となるときがありません。ねっ。終了条件である1にならないので、上記のプログラムは永遠に終わりませんよね。
このことを実感してもらうために、お手元に電卓を用意してみてください。私のはカシオの8桁の電卓なので、それを例にします。もちろん、Windowsの電卓でもかまいません。
(1) まず、数字で“0.0999999”と入力してください。
(2) 次に、“+”を二度続けて押します。すると、左端に“K”というアルファベットが出ると思いますが、これは定数計算といって、定数で計算する式を先に覚えさせるという機能が働いた証です(すみません。他のメーカーの場合は「電卓」「定数計算」とかいうキーワードで検索してみてください)。Windowsの電卓でも“K”は出ませんが、数字を入れて“+”を二度続けて押すことで定数計算ができるようになります。
(3) では、“=”キーを押してみてください。1回押すたびに定数として覚えさせた“0.0999999”が加算されていくと思います。
この方法を使えば、単に“=”キーを連打するだけで繰り返し加算ができますので、押した回数を意識しながらどんどん押してみてください。誤差がどんどん大きくなっていくのが実感できると思います。
次回は、こうした問題にどう対応すればよいかといった話題を扱います。(^^)
誤差は、気にしなくていい場面も数多くありますが、状況によっては無視できないこともまた同様に数多くあります。ご存知の方もいらっしゃると思いますが、ここでひとつの例をご紹介しましょう。
コンピュータに何かをさせようとする場合、誤差は常に意識しなければいけません。たとえば、「0.1を順次足していき、合計が1になったら終了しろ」というプログラムを作ろうとした場合、一般的には次のような手順を書くことになると思います。
1: 変数xに、ゼロを代入(x=0)
2: プログラムの繰り返し点:
3: 変数x自身に0.1を加算(x=x+0.1)
4: 変数xの値を検査し、
1でなければ“プログラムの繰り返し点”に戻る
(1であれば、次のステップがないので終了する)
普通なら、0.1を10回加算すれば1になりますから、このプログラムはちょうど10回目の加算を終えた直後で終了するはずです。でも、このとき、コンピュータ内部で0.1が本当に0.1でなかったらどうなるでしょうか。たぶん、加算結果が1になることはないでしょうから、このプログラムは永遠に終わりません。
そんな馬鹿な、と思われるかもしれません。でも、ここで前回の話を少し思い出してみてください。0.1を2進数に変換すると0.0001100110011……というように、循環小数となってしまいます。コンピュータは無限の数を扱うことはできないためどこかで調整をすることになりますが、一般にはある桁で切り捨てが使われるので、実際には0.1よりもわずかに小さい値となります。極論すれば、10進数の0.1は、2進数となった時点で10進数の0.09999999999……という数に近い値となるわけです。
実際には、0.9999999999……は近似値で1となりますので極端に神経質になる必要はありませんが、先ほどのプログラムに当てはめると、0.09999999999……を10回加算した結果は0.9999999999……ですから1ではありませんよね。で、11回目の加算をした結果は1.0999999999……ですから、ちょうど1となるときがありません。ねっ。終了条件である1にならないので、上記のプログラムは永遠に終わりませんよね。
このことを実感してもらうために、お手元に電卓を用意してみてください。私のはカシオの8桁の電卓なので、それを例にします。もちろん、Windowsの電卓でもかまいません。
(1) まず、数字で“0.0999999”と入力してください。
(2) 次に、“+”を二度続けて押します。すると、左端に“K”というアルファベットが出ると思いますが、これは定数計算といって、定数で計算する式を先に覚えさせるという機能が働いた証です(すみません。他のメーカーの場合は「電卓」「定数計算」とかいうキーワードで検索してみてください)。Windowsの電卓でも“K”は出ませんが、数字を入れて“+”を二度続けて押すことで定数計算ができるようになります。
(3) では、“=”キーを押してみてください。1回押すたびに定数として覚えさせた“0.0999999”が加算されていくと思います。
この方法を使えば、単に“=”キーを連打するだけで繰り返し加算ができますので、押した回数を意識しながらどんどん押してみてください。誤差がどんどん大きくなっていくのが実感できると思います。
次回は、こうした問題にどう対応すればよいかといった話題を扱います。(^^)

渡辺 俊雄(わたなべ としお)
株式会社オーグメント 代表取締役
1958年、東京生まれ。メーカー系システムエンジニア、大手コンピュータ出版社の書籍編集者、インターネット関連組織の広報などを経て2006年に独立。大学生と高校生の二人の子どもを持つ。
ご意見・ご要望、お待ちしています!
この記事に対する皆様のご意見、ご要望をお寄せください。今後の記事制作の参考にさせていただきます。(なお個別・個人的なご質問・ご相談等に関してはお受けいたしかねます。)
「教育エッセイ」の最新記事
