Why that logic
NaN
means Not a Number
. What is not a number? Anything. You can have anything in one side and anything in the other side, so nothing guarantees that both are equals. NaN
is calculated with Double.longBitsToDouble(0x7ff8000000000000L)
and as you can see in the documentation of longBitsToDouble
:
If the argument is any value in the range 0x7ff0000000000001L
through
0x7fffffffffffffffL
or in the range 0xfff0000000000001L
through
0xffffffffffffffffL
, the result is a NaN
.
Also, NaN
is logically treated inside the API.
Documentation
/**
* A constant holding a Not-a-Number (NaN) value of type
* {@code double}. It is equivalent to the value returned by
* {@code Double.longBitsToDouble(0x7ff8000000000000L)}.
*/
public static final double NaN = 0.0d / 0.0;
By the way, NaN
is tested as your code sample:
/**
* Returns {@code true} if the specified number is a
* Not-a-Number (NaN) value, {@code false} otherwise.
*
* @param v the value to be tested.
* @return {@code true} if the value of the argument is NaN;
* {@code false} otherwise.
*/
static public boolean isNaN(double v) {
return (v != v);
}
Solution
What you can do is use compare
/compareTo
:
Double.NaN
is considered by this method to be equal to itself
and greater than all other double
values (including
Double.POSITIVE_INFINITY
).
Double.compare(Double.NaN, Double.NaN);
Double.NaN.compareTo(Double.NaN);
Or, equals
:
If this
and argument
both represent Double.NaN
, then
the equals
method returns true
, even though
Double.NaN==Double.NaN
has the value false
.
Double.NaN.equals(Double.NaN);
In [1]: NaN==NaN Out[1]: False
– BastDouble.NaN==Double.NaN
should indeed return true ifDouble.NaN
were of typejava.lang.Double
. However, its type is the primitivedouble
, and the operator rules fordouble
apply (which demand this inequality for conformance with IEEE 754, as explained in the answers). – GarageString h = "Hello"; // not a number
assertFalse(h != h); // is false
Double.NaN behaviour certainly ain't intuitive... – Statehood