我有以下代码:
Double i=17.31;
long j=(long) (i*100);
System.out.println(j);
O/P : 1730//预期:1731
Double i=17.33;
long j=(long) (i*100);
System.out.println(j);
O/P : 1732//预期:1733
Double i=17.32;
long j=(long) (i*100);
System.out.println(j);
O/P : 1732//预期:1732{如预期}
Double i=15.33;
long j=(long) (i*100);
System.out.println(j);
O/P : 1533//Expected:1533{as Expected}
我已尝试谷歌但无法找到原因。如果问题微不足道,我很抱歉。
最佳答案
似乎没有一个答案涉及为什么 17.32
表现不同。
1。为什么会发生
您在 17.32
和 17.33 & 17.31
之间看到的行为差异是由于 IEEE-754 Rounding 规则造成的。
应用的舍入规则:从,The Java™ Virtual Machine Specification §2.8.1
The rounding operations of the Java virtual machine always use IEEE 754 round to nearest mode. Inexact results are rounded to the nearest representable value, with ties going to the value with a zero least-significant bit. This is the IEEE 754 default mode. The Java virtual machine does not give any means to change the floating-point rounding mode
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...
5。转换到长
编辑:正如@Jeppe Stig Nielsen 所说,在乘法步骤中还有一个因素在起作用。 FP 乘法 ( Reference ) 步骤的结果会向最近舍入。 这会改变结果是否符合预期,但原因仍然与上述完全相同。
最后,由于转换 (long)
,会发生截断,并留下您看到的结果。 (1730, 1732, 1732)
缩小原始转换:The Java™ Language Specification §5.1.3
If the floating-point number is not an infinity, the floating-point value is rounded to an integer value V, rounding toward zero using IEEE 754 round-toward-zero mode
关于java - 双倍乘以 100 然后转换为 long 给出了错误的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13467849/