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)?
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.
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.
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.
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.
You can use
Double.compare(a, b) == 0
From the javadoc for compareTo
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With