事例が見つかるたびに騒ぎになっているようです。今回は、「8.2 – 7.2」の結果が1より小さくなってしまうというものです。最初に非難されたのは例によってExcelのようですが、他の環境でもこういう問題は起こります(C言語の例・Rubyの例)。
#include <stdio.h> int main() { double x = 8.2 - 7.2; if (x >= 1) printf("x >= 1"); else printf("x < 1"); return 0; }
「コンピュータは数値を2進数としてしか表せなくて・・・」という説明をよく見ますが、この説明は間違いです。これでは、「コンピュータは正しい計算ができない」という誤解を生んでしまいます。
10進数の1, 2, 3, …を2進数の1, 10, 11, …で表すという具合に、数を2進数で直接表現しようとするとこういう問題が起きますが、別の表現方法を用いれば、このような問題は起きません。実際、Mathematicaは正しく計算します。
With[{x = 8.2 - 7.2}, If[x >= 1, "x >= 1", "x < 1"]] x >= 1
コンパイルしても大丈夫です。(UMMでは動かないようです。)
f = Compile[{a, b}, With[{x = a - b}, Print[If[x >= 1, "x >= 1", "x < 1"]]]]; f[8.2, 7.2] x >= 1
C言語やRubyではどうすればいいのかというと、許容可能な誤差を決めておいて、その範囲内はよしとするのです。
さらに、この許容可能な誤差は、扱う数によって変えなければならないことに注意してください。以下の例では、許容可能な誤差を1より大きくしなければなりません(実行結果)。
#include <stdio.h> int main() { double a = 9007199254740992; double b = a + 1; if (a == b) printf("a==b"); return 0; }
こういうことは、『Microsoft Visual C++入門』の3.2.11項「浮動小数点についての注意」にちゃんと書いてあったりします。ですから、入門を終えたプログラマはこういうことは知っています。
Excelのような、こうことは知らないであろう人が使うソフトウェアでは、こういう工夫をしなくても正しく計算できるようにしておいてほしいものです。フェルマーの最終定理の「反例」のような冗談を言っているうちはいいのですが、「x >= 0.6 なら合格」というようなことって、よくやられているのではないでしょうか(ボーダーの学生が間違って不合格になる危険があります)。間違いが公になるときには、「採点ミス」になるのでしょうか。