答えはどれも、なぜ 17.32
違う行動をとったのかを扱っているようには見えません。
1. 発生理由
17.32
とで見られる動作の違いは17.33 & 17.31
、IEEE-754 の丸め規則によるものです。
適用される丸め規則: Java™ 仮想マシン仕様 §2.8.1 から
Java 仮想マシンの丸め操作では、IEEE 754 丸めモードが常に使用されます。不正確な結果は、最も近い表現可能な値に丸められ、同点は最下位ビットがゼロの値になります。これは IEEE 754 のデフォルト モードです。Java 仮想マシンは、浮動小数点の丸めモードを変更する手段を提供しません。
2. あなたのケース:
Double は: (1 符号ビット + 11 指数ビット + 52 小数ビット = 64 ビット)。以下の丸め後の内部表現:
1 [63] 11 [62-52] 52 [51-00]
Sign Exponent Fraction
17.31 --> 0 (+) 10000000011 (+4) 1.0001010011110101110000101000111101011100001010001111
17.32 --> 0 (+) 10000000011 (+4) 1.0001010100011110101110000101000111101011100001010010 //rounded up
17.33 --> 0 (+) 10000000011 (+4) 1.0001010101000111101011100001010001111010111000010100
3. 内部表現 (証明):
17.31: (仮数比較)
Actual: 1.00010100111101011100001010001111010111000010100011110...
Internal: 1.0001010011110101110000101000111101011100001010001111
17.32: (仮数比較)
Actual: 1.00010101000111101011100001010001111010111000010100011...
Internal: 1.0001010100011110101110000101000111101011100001010010 //round-up!
17.33: (仮数比較)
Actual: 1.00010101010001111010111000010100011110101110000101000...
Internal: 1.0001010101000111101011100001010001111010111000010100
4. 10 進数に戻す変換:
17.31 -> 17.309999999999998721023075631819665431976318359375...
17.32 -> 17.32000000000000028421709430404007434844970703125... //(was rounded up)
17.33 -> 17.3299999999999982946974341757595539093017578125...
( IEEE-754 解析ツール)
5.ロングキャスト
編集: @Jeppe Stig Nielsen が言ったように、乗算ステップでより多くの要因があります。FP乗算 ( Reference ) ステップの結果は、最も近い方向への独自の丸めを行います。これにより、期待どおりの結果とそうでない結果が変わりますが、理由は上記とまったく同じです。
最後に、キャスト(long)
により切り捨てが発生し、表示される結果が残ります。(1730, 1732, 1732)
プリミティブ変換のナローイング : Java™ 言語仕様 §5.1.3
浮動小数点数が無限大でない場合、浮動小数点値は整数値 V に丸められ、IEEE 754 round-toward-zero モードを使用してゼロに丸められます。