Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manipulating and comparing floating points in java

In Java the floating point arithmetic is not represented precisely. For example this java code:

float a = 1.2; 
float b= 3.0;
float c = a * b; 
if(c == 3.6){
    System.out.println("c is 3.6");
} 
else {
    System.out.println("c is not 3.6");
} 

Prints "c is not 3.6".

I'm not interested in precision beyond 3 decimals (#.###). How can I deal with this problem to multiply floats and compare them reliably?

like image 878
Praneeth Avatar asked May 24 '10 09:05

Praneeth


People also ask

How do you compare floating points in Java?

The compare() method of Float Class is a built-in method in Java that compares the two specified float values. The sign of the integer value returned is the same as that of the integer that would be returned by the function call. Parameters: The function accepts two parameters: f1: The first float value to be compared.

What is a better way to compare floating point values?

To compare two floating point values, we have to consider the precision in to the comparison. For example, if two numbers are 3.1428 and 3.1415, then they are same up to the precision 0.01, but after that, like 0.001 they are not same.

Does == work for floats Java?

According to this java. sun page == is the equality comparison operator for floating point numbers in Java. Java has a defined behavior for floats. The term used in the IEEE-754 standard is “significand,” not “mantissa.” The leading bit of the significand is 1 only if the exponent field is 1-254.

What are the two approaches used for comparing floating point numbers?

There are 4 (5) different ways to compare floating-point numbers. They are: Bitwise comparison. Direct ("exact") IEEE-754 comparison.


2 Answers

I think it has nothing to do with Java, it happens on any IEEE 754 floating point number. It is because of the nature of floating point representation. Any languages that use the IEEE 754 format will encounter the same problem.

As suggested by David above, you should use the method abs of java.lang.Math class to get the absolute value (drop the positive/negative sign).

You can read this: http://en.wikipedia.org/wiki/IEEE_754_revision and also a good numerical methods text book will address the problem sufficiently.

public static void main(String[] args) {
    float a = 1.2f;
    float b = 3.0f;
    float c = a * b;
        final float PRECISION_LEVEL = 0.001f;
    if(Math.abs(c - 3.6f) < PRECISION_LEVEL) {
        System.out.println("c is 3.6");
    } else {
        System.out.println("c is not 3.6");
    }
}
like image 156
Daniel Baktiar Avatar answered Sep 26 '22 21:09

Daniel Baktiar


It's a general rule that floating point number should never be compared like (a==b), but rather like (Math.abs(a-b) < delta) where delta is a small number.

A floating point value having fixed number of digits in decimal form does not necessary have fixed number of digits in binary form.

Addition for clarity:

Though strict == comparison of floating point numbers has very little practical sense, the strict < and > comparison, on the contrary, is a valid use case (example - logic triggering when certain value exceeds threshold: (val > threshold) && panic();)

like image 28
bobah Avatar answered Sep 25 '22 21:09

bobah