事務計算とコンピュータ - 異常の原因と対策 (続き)

  130.2 * 1000 = 130199
という予想外の結果になる原因は、 身の回りのコンピュータが有限な桁数の2進数を使うことにあります。 10 進法の有限小数が 2 進法で無限小数になることことがあって、 このケースでも、

10 進数の 130.2 は、64 ビットの浮動小数点(IEEE 754 の Double Format)で

+2^7*1.000001000110011001100111111111111111111111111111111
と、無限小数の小数点以下 53 桁以降を切捨てた形になります。 数値としては、この後に 1 が無限に続くのですが、 コンピュータのメモリは有限ですから、 小数で扱う限り、どこかで打ち切るしかありません。

一方、10 進数の 1000 は、2 進の浮動小数点で

+2^9*1.1111010000000000000000000000000000000000000000000000
となって、無限小数にはなりませんが、この2つを乗算した「130.2*1000」は 2 進数で、

+2^16*1.1111110010010111111111111111111111111111111111111111
となって、やはり無限小数になります。

つまり、 結果は 130200 に極めて近いのですが、有限桁で打ち切られた分だけ、 130200 より小さくなって、 小数部を切り捨てると 130199 になってしまうという仕組みなのです。

原因がわかれば対策は簡単で、小数部を切り捨てる前に

+2^16*0.0000000000000000000000000000000000000000000000000001
以上で結果に影響を与えない小さな数、例えば、1e-6 を加えておくといった方法が 簡単だと思います。

awk の数値は内部的にすべて double として扱いますので、 こういった細工が不可欠ですが、 c の場合は浮動小数点を使わずに整数を使って、 小数を使わないようにプログラムすることもできます。

平林 浩一, 2001