Results 1 to 7 of 7
  1. #1
    sardare is offline Member
    Join Date
    Jun 2008
    Posts
    17
    Rep Power
    0

    Default 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. #2
    pbrockway2 is offline Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,565
    Rep Power
    12

    Default

    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. #3
    fishtoprecords's Avatar
    fishtoprecords is offline Senior Member
    Join Date
    Jun 2008
    Posts
    571
    Rep Power
    7

    Default

    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. #4
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    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.

  5. #5
    fishtoprecords's Avatar
    fishtoprecords is offline Senior Member
    Join Date
    Jun 2008
    Posts
    571
    Rep Power
    7

    Default

    Quote Originally Posted by toadaly View Post
    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. #6
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    Quote Originally Posted by fishtoprecords View Post
    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. #7
    Steve11235's Avatar
    Steve11235 is offline Senior Member
    Join Date
    Dec 2008
    Posts
    1,046
    Rep Power
    7

    Default

    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.

Similar Threads

  1. number of floating point
    By mohammad8065 in forum Advanced Java
    Replies: 5
    Last Post: 12-28-2008, 09:41 AM
  2. Floating point values in SWT Spinner
    By Java Tip in forum SWT Tips
    Replies: 0
    Last Post: 07-07-2008, 04:50 PM

Posting Permissions

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