可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
This code
Double dbl = 254.9999999999999; Integer integ = dbl.intValue(); System.out.println(integ);
shows 254, but one "9" more
Double dbl = 254.99999999999999; Integer integ = dbl.intValue(); System.out.println(integ);
and it is already 255.. Why?
回答1:
To know the exact value of your double, you can use a BigDecimal:
System.out.println(new BigDecimal(254.9999999999999)); System.out.println(new BigDecimal(254.99999999999999));
prints:
254.9999999999998863131622783839702606201171875 255
So this is simply due to (limitations of) double precision...
回答2:
System.out.println(254.9999999999999 == 255.0); System.out.println(254.99999999999999 == 255.0);
prints
false true
That should give you a hint. The double
type can represent up to 16 significant digits, and your literal has 17. Therefore the double
value nearest to the second decimal literal is 255.0
.
For the second line of code, Eclipse actually issues a warning:
Comparing identical expressions
because it is already the compiler which is aware of the fact that these are just two literals for the exact same double
value.
回答3:
A double is a 64-bit binary floating point representation of a number. Binary floating point numbers cannot exactly represent most decimal fractions. They can exactly represent 1/2, 1/4, 1/64+1/32 etc but they cannot exactly represent 0.9 or 0.1. Furthermore their precision is limited.
In your case, 254.99999999999999 has exactly the same representation as 255.0 internally. You can see this by checking a hexadecimal version of the binary fraction, using the Double.toHexString
method. Because 254.99999999999999 is already equal to 255.0, when you cut off the fractional part by casting it to a 32-bit integer, you end up with 255.
System.out.println("a: " + Double.toHexString(254.99999999999999d)); System.out.println("b: " + Double.toHexString(255d));
Output
a: 0x1.fep7 b: 0x1.fep7
回答4:
The answer is rather simple. The decimal number you wrote in your code with one 9 more is closer to the double which represents exactly 255 than any other double. So, the double that is used in the compilation is exactly equal to 255. While the decimal number with one 9 less is optimally represented with a double I show below. This means that it lies closer to that specific double than any other double.
Check out this demo: http://ideone.com/hSqJTJ
This is the output:
Original double: 254.9999999999999 Cast to int: 254 Exact double: 254.9999999999998863131622783839702606201171875 Original double: 255.0 Cast to int: 255 Exact double: 255
回答5:
double binary format is sign (1) + exponent (11) + fraction (53). Binary form for 254.9999999999999
and 254.99999999999999
is
0 10000000110 1111110111111111111111111111111111111111111111111100 0 10000000110 1111111000000000000000000000000000000000000000000000
we can get it as Long.toString(dbl.doubleToLongBits(dbl), 2);
integer part is
1111110 1111111
leading 1 bit is omitted so actual integer values are
11111110 - 254 11111111 - 255
note that cast double to integer is done not by rounding but truncation