Java で何故 4.0 - 3.10 は 0.90 ではない ?
twitter で流れてきたツイートで以下のようなものがありました。
Why 4.0 - 3.10 not equal to 0.90 ?
public static void main(String args[]) { double x = 4.0 - 3.10; System.out.println(x == 0.90); }
結果: false
ツイートに対する返信で、「double や float を比較するのに == を使ってはならない。」というものがありましたが・・・。
実際にこの値を取得してみると [0.8999999999999999] という値が得られます。
なぜ誤差が生じるのか?
つまりは、2進浮動小数点 で演算しているので、広い範囲の桁数を扱うことになった場合は、近似値を取得しようとするので、その時点で正確な値ではなくなってしまうということだと思っています。
誤差が生じないケース?
0.5(10進数) -> 0.1(2進数)
0.5 のように、2進数に有効桁で変換出来る数値であれば問題ない。
double y = 0.5 - 0.25; System.out.println(y); // 0.25
誤差が生じるケース?
0.1(10進数) -> 0.00011001100110011....(2進数)
0.1 のように、2進数では表現ができない(循環小数や無限小数)数値だと、どこかで桁の丸めが発生するので、その時点で誤差(丸め誤差)が発生することになる。
double z = 0.30 - 0.20; System.out.println(z); // 0.09999999999999998
※ただし、答えが 0.1 になる全ての演算で誤差になる訳ではなさそうです
double p = 0.20 - 0.10; System.out.println(p); // 0.1
どこの桁で丸めが発生するかに依存するように思います。
0.00110011001100 (0.2) -) 0.00011001100110 (0.1) 0.00011001100110 (0.1)