次のコードはなぜですか:
System.out.println((int)(19.99 * 100));
結果「1998」を生成しますか?
丸め誤差。キャストなしで計算の結果を見ると、次のようになります。
1998.9999999999998
したがって、int にキャストすると、小数部分は切り上げられずに切り捨てられ、1998 になります。
教訓は、正確な答えが必要な場合は、float / double をまったく使用しないことです。お金のような離散値について話している場合は、int を使用して原子単位 (ペンスなど) を扱います。正確な小数が必要な場合は、それBigDecimal
があなたの友達です。
を使用Math.round()
して結果を期待どおりの場所に移動することはできますが、これはすべての場合に機能するわけではなく、根本的な問題に対処することはできません。
これは、19.99 を正確に表すことができないためです。
System.out.println(new BigDecimal(19.99));
これが実際に表す値を出力します。これは、表すことができる 19.99 に最も近い値です。
19.989999999999998436805981327779591083526611328125
そして19.99 * 100
_
System.out.println(new BigDecimal(19.99 * 100));
これは
1998.999999999999772626324556767940521240234375
問題は、19.99 に表現エラーがあることです。100 を掛けると、わずかに小さすぎる数値が得られます。
100 を掛けて切り捨てる(int)
と、1998 年になると予想されます。
代替案は
System.out.println(Math.round(19.99 * 100));
19.99 * 100 の計算は 1998.999999 になり、それを int にキャストしているため、小数部分が破棄されます。
これは、丸めの問題によるものです。double
これらの問題が発生し float
やすいため、このBigDecimal
クラスを使用することをお勧めします。
このコードは、期待されるものを出力する必要があります。
BigDecimal bg = new BigDecimal("19.99");
System.out.println(bg.multiply(new BigDecimal("10")));
これにより、次の結果が得られます。
199.90
System.out.println((19.99 * 100));
intキャストを追加することにより、結果 1998.9999999999998 を生成します。小数部分を切り捨て、1998 を返します。
浮動小数点データ型 (Java では float および double) は、ほとんどの 10 進数値を近似的にしか表すことができません。詳細については、このテーマに関するJoshua Bloch の知恵の言葉を参照してください。