I am working on understanding the limitations of double. 0.1 cannot be expressed in a finite system because it is a repeating binary value. But, when I declare a variable and give it 0.1, it still prints as 0.1 and not .0999999999999999, 1.000000000000001 or something of the like. But, if I add a variable that has 0.1 ten times, it comes out to .9999999999999999, which is what I would expect.
The real question is why is it printing exactly at 0.1 when I know that is impossible and I have proof that is not the true value?
double d = 0.1;
System.out.printf("%.16f\n",d);
System.out.printf("%.16f", d + d + d + d + d + d + d + d + d + d);
What I am trying to do is compare a string literal to a double conversion to see if the value in the string can be exactly represented in double. For example:
".5" == .5? Expected answer: Yes.
".1" == .1? Expected answer: No.
The comparison I am trying is
number = new BigDecimal("0.1");
d = number.doubleValue();
if (number.compareTo(new BigDecimal(Double.toString(d))) == 0){
// Doing something
}
Any help understanding why this is not distinguishing between values that can and cannot be represented by double would be appreciated.
To test if a String
represents a double
value you can do this:
private static boolean isADouble(String s) {
return new BigDecimal(s).equals(new BigDecimal(Double.parseDouble(s)));
}
public static void main(String[] args) {
System.out.println(isADouble("0.1")); // false
System.out.println(isADouble("0.5")); // true
}
This works because new BigDecimal(s)
produces a BigDecimal
exactly equal to the value represented by the String
, whereas new BigDecimal(Double.parseDouble(s))
is the exact value of the closest double
to that value.
I will explain at the end why number.compareTo(new BigDecimal(Double.toString(d))) == 0
does not work.
When you do
double d = 0.1;
System.out.println(d);
you get the answer 0.1
because d
is the closest double
to the "real" 0.1
. (double d = 0.1;
means "make d
the nearest double
to 0.1
". When you write
System.out.println(d + d + d + d + d + d + d + d + d + d);
you see 0.9999999999999999
rather than 1
. The reason you don't see 1
is because there are double
values closer to one than the answer (in fact one is a double
value itself). There is no reason why the answer should be the closest double
to one, because d
wasn't really 0.1
in the first place (it was just close to it), and in any case when you add floating point numbers inaccuracies are introduced.
Finally, number.compareTo(new BigDecimal(Double.toString(d))) == 0
does not work because even though number.doubleValue()
is not exactly 0.1
, Double.toString()
still converts it to the String
"0.1"
because there are no double
values closer the "real" 0.1
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With