While answering this question, I got these confusing results:
double d = 0.49999999999999990d; //output 0.4999999999999999 as expected
d = 0.49999999999999991d; //output 0.4999999999999999
d = 0.49999999999999992d; //output 0.49999999999999994
d = 0.49999999999999993d; //output 0.49999999999999994
d = 0.49999999999999994d; //output 0.49999999999999994 as expected
d = 0.49999999999999995d; //output 0.49999999999999994
d = 0.49999999999999996d; //output 0.49999999999999994
d = 0.49999999999999997d; //output 0.49999999999999994
d = 0.49999999999999998d; //output 0.5
Why is this behaviour showing?
NOTE: I got these outputs just by printing d; I mean I used:
System.out.println(d);
Floating point types cannot exactly represent all Real numbers. In fact, a
doubleis a 64-bit floating point type, and can therefore only represent 264 different values … and there are an infinite number of Real numbers. (Indeed, there are an infinite number of Real numbers between0.49999999999999990dand0.49999999999999999d.)You have picked some numbers that fall between consecutive values in the set-of-all
doublevalues. In other words, you’ve exceeded the limits of precision for thedoubletype.What can you do about it? Well one way to get more precision is to use the
BigDecimalclass, which can (in theory) give you in the region of 2 BILLION decimal digits of precision. The downside is that your code will be more complicated … and significantly slower, depending on how much precision you use.The other approach is to recognize that you probably don’t need that much precision.