Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is there a difference between the same value stored as a float and a double in Java?

I expected the following code to produce: "Both are equal", but I got "Both are NOT equal":

float a=1.3f;
double b=1.3;
if(a==b)
{
 System.out.println("Both are equal");
}
else{
 System.out.println("Both are NOT equal");
}

What is the reason for this?

like image 741
AnandBabu Avatar asked Oct 01 '09 06:10

AnandBabu


1 Answers

It's because the closest float value to 1.3 isn't the same as the closest double value to 1.3. Neither value will be exactly 1.3 - that can't be represented exactly in a non-recurring binary representation.

To give a different understanding of why this happens, suppose we had two decimal floating point types - decimal5 and decimal10, where the number represents the number of significant digits. Now suppose we tried to assign the value of "a third" to both of them. You'd end up with

decimal5 oneThird = 0.33333
decimal10 oneThird = 0.3333333333

Clearly those values aren't equal. It's exactly the same thing here, just with different bases involved.

However if you restrict the values to the less-precise type, you'll find they are equal in this particular case:

double d = 1.3d;
float f = 1.3f;
System.out.println((float) d == f); // Prints true

That's not guaranteed to be the case, however. Sometimes the approximation from the decimal literal to the double representation, and then the approximation of that value to the float representation, ends up being less accurate than the straight decimal to float approximation. One example of this 1.0000001788139343 (thanks to stephentyrone for finding this example).

Somewaht more safely, you can do the comparison between doubles, but use a float literal in the original assignment:

double d = 1.3f;
float f = 1.3f;
System.out.println(d == f); // Prints true

In the latter case, it's a bit like saying:

decimal10 oneThird = 0.3333300000

However, as pointed out in the comments, you almost certainly shouldn't be comparing floating point values with ==. It's almost never the right thing to do, because of precisely this sort of thing. Usually if you want to compare two values you do it with some sort of "fuzzy" equality comparison, checking whether the two numbers are "close enough" for your purposes. See the Java Traps: double page for more information.

If you really need to check for absolute equality, that usually indicates that you should be using a different numeric format in the first place - for instance, for financial data you should probably be using BigDecimal.

like image 176
Jon Skeet Avatar answered Oct 20 '22 00:10

Jon Skeet