Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check two float/double values for exact equality

What is an elegant, readable and non-verbose way of comparing two floating point value for exact equality?

As simple as it may sound, its a wicked problem. The == operator doesn't get the job done for NaN and also has special treatment for zero:

(+0.0 == -0.0) -> true
Double.NaN == Double.NaN -> false

But I want to determine if two values are exactly the same (but I do not care for different NaN patterns, so any NaN == any other NaN -> true).

I can do this with this ugly Monster piece of code:

Double.doubleToLongBits(a) == Double.doubleToLongBits(b)

Is there a better way to write this (and make the intent obvious)?

like image 858
Durandal Avatar asked Mar 22 '13 14:03

Durandal


People also ask

Can we use == to compare two float or double numbers?

Using the == Operator As a result, we can't have an exact representation of most double values in our computers. They must be rounded to be saved. In that case, comparing both values with the == operator would produce a wrong result.

How do you compare two float 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.

How do you test the equality of a float?

If the integer representations of two same-sign floats are subtracted then the absolute value of the result is equal to one plus the number of representable floats between them. In other words, if you subtract the integer representations and get one, then the two floats are as close as they can be without being equal.

How do you know if two doubles are equal?

equals() is a built-in function in java that compares this object to the specified object. The result is true if and only if the argument is not null and is a Double object that contains the same double value as this object. It returns false if both the objects are not same.


2 Answers

You can use

Double.compare(a, b) == 0

From the javadoc for compareTo

  • Double.NaN is considered by this method to be equal to itself and greater than all other double values (including Double.POSITIVE_INFINITY).
  • 0.0d is considered by this method to be greater than -0.0d.
like image 166
Peter Lawrey Avatar answered Nov 15 '22 18:11

Peter Lawrey


What you've got is already the best way of doing it, I'd say. It makes it clear that you're interested in the bitwise representation of the value. You happen to be converting those bits to long as a convenient 64-bit type which doesn't have any funky behaviour.

If you don't want it appearing frequently in your codebase, just add a method to wrap it:

public static boolean bitwiseEqualsWithCanonicalNaN(double x, double y) {
    return Double.doubleToLongBits(x) == Double.doubleToLongBits(y);
}

Note that as per your question, this does not differentiate between different NaN values. If you wanted to do this at a later date, you'd need to use Double.toRawLongBits.

like image 42
Jon Skeet Avatar answered Nov 15 '22 16:11

Jon Skeet