1. Member
Join Date
Jun 2008
Posts
17
Rep Power
0

java floating point comparison

I am doing numerical analysis in Java. Due to all the arithmetic including the use of rounding functions, I often end up with floating point numbers such as 29.400000000000002 or 0.00000000001. I often need to compare such numbers for equality which fails because of the error induced.

How do I compare these numbers? I tried using an epsilon such as
if (Math.abs(a-b) <= EPISLON) { }
but the problem is that the EPSILON is variable and does not always work..

thank you,

Sam

2. Moderator
Join Date
Feb 2009
Location
New Zealand
Posts
4,561
Rep Power
11
I often need to compare such numbers for equality which fails because of the error induced.
I think it makes sense to say that a naive equality test will fail because of the limited precision of floating point representations of quantities.

("Error" suggests that there is something wrong. And there isn't.)

but the problem is that the EPSILON is variable and does not always work.
Perhaps you could say what "does not always work" means?

Sometimes all we want of "a==b" is that the quantities are within some small (fixed) tolerance. So we declare EPSILON as some static final amount and use it as you suggest.

Other times that won't do. For instance the acceptable closeness might be a relative value: a certain proportion of the given values. We might express that with

Java Code:
```static final int FACTOR = ...

if(Math.abs(a-b) <= Math.abs(a+b)/FACTOR) {
...```
(For instance if we made FACTOR 2 million then equality would be true if the difference was less than one millionth of their average value. Dealing with negatives would be a pain...)

It would seem to depend on the details of what you are trying to do: ie on what "doesn't work" means in this case.
Last edited by pbrockway2; 03-01-2009 at 01:15 AM. Reason: typo

3. Your question is not really a Java question, the same topic comes up in all languages that use floating point. Your "problem" is not a problem, its a feature of how floating point works on computers.

Your "EPISLON" comment about it being a variable is not technically correct, its only a variable if you write your code to have it as a variable. But variable or constant, that's not the solution.

@pbrockway2's hints are in the right direction, but you really need to engineer the numerical analysis of your algorithm. You should google for "numerical analysis". The proper answer depends on your problem domain, and what kinds of calculations are being done.

4. Senior Member
Join Date
Jan 2009
Posts
671
Rep Power
5
Numerical analysis requires that you keep track of the maximum possible error your self, and then compare consider all numbers that are within that error bound as equivalent.

That's hard.

The easier approach, is to use integer math instead of floating point math. If a long does not give you enough significant digits, you can use a BigInteger.

The easier approach, is to use integer math instead of floating point math. If a long does not give you enough significant digits, you can use a BigInteger.
Using BigInteger is not practical for a lot of things. Its domain specific, but for example, calculating correlation coefficients requires floating point. As does much of engineering.

BigInteger is not a solution to the problem, its designed for exactly what its name is, really big integers.

6. Senior Member
Join Date
Jan 2009
Posts
671
Rep Power
5
Originally Posted by fishtoprecords
Using BigInteger is not practical for a lot of things. Its domain specific, but for example, calculating correlation coefficients requires floating point. As does much of engineering.
Agreed, but in the OP example, it looks like he's using floating point where integer math may be more appropriate. It would be unusual to expect a correlation coefficient to come out to an exact few significant digits.

7. You can use BigDecimal if you need exact representation and calculation of large values with decimal places. However, that's generally reserved for financial applications.

I don't understand why you say your solution doesn't work. First, if you need more precision, use double instead of float. Second, so what if you have a field named epsilon? (Don't use all upper case unless this field is declared static final, which makes it a constant.) You can write a utility class that has a method

public static boolean equalTo(double pValue1, double pValue2, double pEpsilon) {
return pValue1 >= pValue2 ? (pValue1 - pValue2 <= pEpsilon) : (pValue2 - pValue1 <= pEpsilon);
}

This allows you specify the value of epsilon.

Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•