Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing floats and doubles in Java

The following code uses the values of type float and double respectively.

float a=99999.99F;
double b=a;

System.out.println("a : "+a);
System.out.println("b : "+b);
System.out.println("a==b : "+(a==b));

It displays the following output:

a : 99999.99
b : 99999.9921875
a==b : true

After execution, the values of a and b are 99999.99 and 99999.9921875 respectively though a==b returns true.

How does the comparison expression a==b return true?

like image 495
Tiny Avatar asked Dec 19 '13 13:12

Tiny


People also ask

Can I compare float and double in Java?

Yes, instead of using equality operator (==), you can use relational operator e.g. less than (<) or greater than (>) to compare float and double values.

Can you compare float and double?

Double is more precise than float and can store 64 bits, double of the number of bits float can store. Double is more precise and for storing large numbers, we prefer double over float. For example, to store the annual salary of the CEO of a company, double will be a more accurate choice.

Is float faster than double in Java?

Performance-wise there's not likely to be much difference, and double may actually be faster. If Java is being run on a processor that doesn't have a floating-point unit at all, or supports 32-bit floats but not 64-bit floats, then a float could be faster.

Can we use == to compare two float values?

In the case of floating-point numbers, the relational operator (==) does not produce correct output, this is due to the internal precision errors in rounding up floating-point numbers. In the above example, we can see the inaccuracy in comparing two floating-point numbers using “==” operator.


3 Answers

On the final line, where you compare a==b, the value of a is being implicitly promoted to double before the comparison. So, in effect, what is really being evaluated is (((double)a)==b) which, of course, evaluates true, since b was initialized by casting a as double in the first place.

In other words, the last boolean expression (a==b) asks:

is (some float value converted to a double)==(the same float value converted to a double somewhere else)

and the answer is : yes.

UPDATE: a commenter below made a good point: when a is promoted to double, the stored numeric value does not actually change, even though it appears to because a different value is printed. The issue is with how floating point numbers are stored; without making this answer WAAAY too long and wading in past my depth, what you need to know is that some simple decimal values cannot be perfectly represented in binary floating point form, no matter how many digits you have (just like you can't perfectly represent 1/3 in base 10 without an infinite number of 3s, as in 0.333333...), so when you assign one of these values using float (a 32-bit representation of a floating point number) and then you convert it to a double (a 64-bit representation) and then use println to display the value of that number, you may see more digits.

The println method displays the shortest string of decimal digits that convert to the same float (or double) value the computer sees internally. Although the same numerical value is passed as argument in the first two calls to println in your example, the double type has more precision so println needs to print more digits to show “the shortest string of decimal digits that would convert to (double)99999.99F”. If your example had been 9999.50, both numbers would have printed the same, because binary numbers can represent 1/2 just fine.

NOTE: I am not even close to an expert on floating point numbers; you should check out (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) if you want a deeper understanding of what is going on here.

like image 60
JVMATL Avatar answered Oct 19 '22 04:10

JVMATL


It is because in

double b = a;

the float value is converted (widened) to a double, but in

b == a

the same float value in a is again converted to a double to compare it with b. So, the outcome of the 2 conversions is the same.

like image 4
Ingo Avatar answered Oct 19 '22 03:10

Ingo


The reason that printing a and b with:

System.out.println("a : "+a);
System.out.println("b : "+b);

shows different results is because the default floating-point printing for Java shows just enough digits to distinguish the number in its type. In float a=99999.99F;, the value 99999.99 is not exactly representable in float, so it is converted to the nearest representable value (99999.9921875), and a is set to this value.

When a is printed, “99999.99” is all that is needed to show the value.

Then double b=a; sets b to exactly the same value. However, since b is double, there are other representable values in double that are closer to 99999.99. If you had used double b = 99999.99;, the fact that double has more precision means b would have been set to a value closer to 99999.99 (99999.990000000005238689482212066650390625). However, your code has set b to a value farther from 99999.99 than that. So, when b is printed, Java must use more digits to show that its value is not the double that is closest to 99999.99.

Finally, when you compare a and b, the comparison returns true because a and b have exactly the same value.

In summary: a and b are exactly equal, but b is printed with more digits because it is represented more finely in double.

like image 3
Eric Postpischil Avatar answered Oct 19 '22 05:10

Eric Postpischil