
Excelを使った例題
ここに全国的にチェーン展開する飲食会社があるとする。

同社では利用客に5点満点のレビューをお願いしており、年度末に集計している。
昨年・今年のレビュー結果は以下の通り。

さて、社長から「前年より0.1以上高かった支店には金一封を出す」とお達しがあった。

そこで経理担当者はまずExcelに昨年、今年の点数を入力。

次に数式を使って、0.1以上プラスの支店を抽出した。

結果こうなった。

しかしこの方法には落とし穴がある。
それは小数の「計算誤差」というものを考慮していない点だ。
もしお手元にExcelがあるなら試してみて欲しい。次のようにC店の数値を書き換えると〇は消える。

「3.9 – 3.8」と「3.8 – 3.7」の結果はどちらも「0.1」なのに、片方には〇が付いて、もう片方には〇が付かない罠。
わかりやすくする為に、直接数字を使って計算結果を出してみた。

表示上はどちらも「0.1」なのだが、この2つは微妙に違う。
小数点の桁数を増やせば明らかになる。


もちろんこれはコンピュータ側の問題(というか2進数の限界)
人間が10進数で簡単にできる小数計算が、2進数で考えるコンピューターだと正確に表現できないことがあるのだ。
10進数でも「10 / 3 = 3.33333…」といった無限小数はあるが、2進数「3.8 – 3.7 = 0.09999…」もそれに近い。
機械のミスは人の責任になる
上記のように支店が3つならすぐ気づくが、100支店以上あると暗算を省略し、金一封が漏れる支店が出てくる。
そうなると誰が責任を取らされるか? 今回だとExcelを作成した経理担当者だろう。
レアケースなのでこの罠にはまる確率は低いが、仕事でExcelを使う人は一応知識として知っておこう。
正しい数式にする
計算誤差は、2進数で表現できない計算結果が、ほぼそれに近い数値で出ることが問題だ。
なので本来の桁数で四捨五入して、望みの数値に整えてしまえば良い。

今回の場合、小数点1桁同士の引き算なので、小数第2位以下が発生することはない。
「ほぼ0.1の0.09999999……」という結果は「0.1」で受け取るのが妥当だろう。

という訳でROUND関数を使って、最初のif文を修正しよう。
丸めた計算結果と「>=0.1」の判定ならきちんと動作するはずだ。


はっきり言って計算誤差なんてイレギュラーの範疇なので、常に意識して防止するのは困難だ。
しかし、知識があればもし遭遇しても「あれ?これってもしかして……」と気付くはずだ。
備えあれば患いなし。ぼんやりでもいいから憶えておこう。