似乎没有一个答案涉及为什么 17.32
表现不同。
1. 为什么会发生
17.32
您在和之间看到的行为差异17.33 & 17.31
是由于 IEEE-754舍入规则造成的。
应用的舍入规则:来自Java™ 虚拟机规范 §2.8.1
Java 虚拟机的舍入操作始终使用 IEEE 754 舍入到最接近模式。不精确的结果被四舍五入到最接近的可表示值,并与具有零最低有效位的值相匹配。这是 IEEE 754 默认模式。Java 虚拟机没有给出任何改变浮点舍入模式的方法
2. 你的情况:
双精度为:(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. 转换回十进制:
17.31 -> 17.309999999999998721023075631819665431976318359375...
17.32 -> 17.32000000000000028421709430404007434844970703125... //(was rounded up)
17.33 -> 17.3299999999999982946974341757595539093017578125...
(IEEE-754 分析工具)
5.投长
编辑:正如@Jeppe Stig Nielsen 所说,在您的乘法步骤中还有一个因素在起作用。FP乘法 ( Reference ) 步骤的结果会自行向最近舍入。这会改变结果是否符合预期,但原因仍然与上述完全相同。
最后,由于 cast (long)
,会发生截断,并留下您看到的结果。(1730, 1732, 1732)
缩小原始转换:Java™ 语言规范 §5.1.3
如果浮点数不是无穷大,则浮点值四舍五入为整数值 V,使用 IEEE 754 向零舍入模式向零舍入