普段から EXCEL でいろいろと計算させたりチェック作業をしてる人で「10進数から2進数への変換誤差」と聞いて「ああ、はいはい、知ってますよ。それがどうかしました?」という人はこの記事を読む必要はナッシングありません。どうぞ心安らかに日常生活をお過ごしください。
さて、ここからは、EXCELで計算式や関数を活用してるけど、2進数と10進数とか丸め誤差とか言われてもピンとこない方々にお読みいただく部分です。知ってる人には「何をいまさら」って話ですけど、知らない人はこれを読んでる途中で過去に自分が仕事で何かとんでもないことをやらかしてしまってたんじゃないかと背筋がゾクッとするかもしれません。
EXCELで試してみよう
手元にパソコンあったらEXCELを起動しましょう。
あ、EXCELを使いますけど、悪いのはEXCELじゃないです。わたし、日頃からEXCELはクソだとかクソだとかクソだとかクソだとかひどいこと言ってますが、この件についてはEXCELさんも被害者っていえば被害者かな。ま、とりあえずエクスキューズしといたから、あとは言いたい放題言うよ。
EXCELを起動しましたか?
起動したら、A1セルに「0.1」と数字を入力して、B1セルには「=4.9-4.8」という式を入力してください。
入力を確定するとA1セルもB1セルも「0.1」が表示されますね?
ここでA1とB1に違うものが表示されたって人はおっちょこちょいです。このページをそっと閉じてまずは「よくわかるMicrosoft Excel 基礎」とか「すぐわかる はじめて学ぶExcel入門」とかって本を読みましょう。
さて、次にC1セルに『A1セルとB1セルが同じなら「同じ」、違うなら「違う」という文字が出力される』判別式を作ってください。If文を使います。
=IF(A1=B1, “同じ”, “違う”)
さて、A1セルとB1セルは同じだから、C1セルには「同じ」が出力されると思いきや・・・・
「違う」が出力されちゃいました。画面では両方とも同じ0.1なのに、違うという判定になってしまう。これはいったい何が起きてるのか。
D1セルに、A1セル引くB1セルを計算させてみましょう。
0.1 – 0.1 なんだから0になると思いきや
あら? 0.1 引く 0.1 の結果がビミョーにゼロになってない。指数表示だとわかりにくいから小数で表示すると
0.1 よりも 4.9 – 4.8 の答えの方がほんのちょっとだけ大きいってことになってる。
これが、丸め誤差と呼ばれる怪奇現象。
コンピュータは2進法で動いている
ご存知の方が多いと思いますが、コンピュータはあらゆる情報を0と1の組み合わせで記録する機械です。たとえば数値も
10進数の [5] は [101]
10進数の [6] は [110]
10進数の [7] は [111]
みたいに2進数で扱います。
計算も2進法で行われます。たとえば 5 + 7 は、コンピュータの中では2進数に変換されて 101 + 111という2進法の足し算が実行されます。答えは2進数の 1100 で、これを最後に10進数に戻すと 12 になり、答え 12 と表示されます。
10進数を2進数に変換して、2進法で四則演算を実行して、出た答えを10進数に戻す
このとき使われる数値がみな整数であれば10進数←→2進数の変換にまったく問題は起きないんだけど、小数が関係すると問題が起きる可能性が出てくる。たとえば10進数の「0.1」を2進数に変換しようとすると
0.00011001100110011001(1001)・・・・・・
と循環小数になってしまう。このときコンピュータは所定の桁数で丸めてしまうので、誤差が発生。2進数の0.00011001100110011001を10進数に戻すと
0.09999942779541016
で 0.1 には戻らない。
同様に
10進数の「4.9」は2進数で「100.11100110011001100110(0110)・・・・・」
10進数の「4.8」は2進数で「100.11001100110011001100(1100)・・・・・」
なので所定の桁数で丸められ、4.9 – 4.8 の計算結果は丸めた数値同士の引き算になるので、計算結果に誤差が発生する。そのため 4.9 – 4.8 の計算結果が 0.1 と微妙に違うという結果になってしまう。とまあそういうことらしい。
EXCELはその涙ぐましい努力によって画面の見た目では A1セルもB1セルも同じ0.1を表示してくれてるものの、実際の情報は誤差を含んだ状態でしか記録できていない。その結果、同じはずの2つの結果が違うということになる。
IF文とかで計算結果の比較したことある?
小数が関係する計算は誤差が含まれる可能性があるので、上記のように比較式に使うと同じはずの数値が、違うと判定されることが起きてしまう。
ここまで読んで、背中に冷たいものを感じた人がいるかもしれない。
大量の計算結果同士を比較してIF文で同じかどうか判別して集計に使ったりしたことがある人、あの時の集計結果は本当に正しかったのだろうか?
いやーっ