为什么Double.NaN == Double.NaN返回false?

问题

我只是在研究OCPJP问题,我发现了这个奇怪的代码:

public static void main(String a[]) {
    System.out.println(Double.NaN==Double.NaN);
    System.out.println(Double.NaN!=Double.NaN);
}

当我运行代码时,我得到了:

false
true

当我们比较两个看起来彼此相同的东西时,输出false怎么样?什么NaN美元?


#1 热门回答(129 赞)

NaN表示"不是数字"。

Java Language Specification (JLS) Third Edition says

溢出的操作产生有符号的无穷大,下溢的操作产生非规范化值或有符号零,并且没有数学定义结果的操作产生NaN。以NaN作为操作数的所有数值运算都会产生NaN。如已经描述的那样,NaN是无序的,因此涉及一个或两个NaN的数字比较操作返回false,并且涉及NaN的任何!=比较返回true,包括当x是NaN时x!= x。


#2 热门回答(60 赞)

根据定义,NaN不等于包括NaN的任何数字。这是IEEE 754标准的一部分,由CPU / FPU实现。这不是JVM必须添加任何支持逻辑的东西。
http://en.wikipedia.org/wiki/NaN>与NaN进行比较,即使与自身进行比较,也始终返回无序结果。 ...相等和不等式谓词是非信令的,因此x = x返回false可用于测试x是否是安静的NaN。

Java将所有NaN视为安静的NaN。


#3 热门回答(46 赞)

为什么那个逻辑
NaNmeansNot a Number。什么不是数字?任何东西。你可以在一边有任何东西,在另一边有任何东西,所以没有什么可以保证两者都是等于.NaN是用Double.longBitsToDouble(0x7ff8000000000000L)计算的,你可以在longBitsToDouble的文档中看到:

如果参数是0x7ff0000000000001L到0x7fffffffffffffffL范围内的任何值或0xfff0000000000001L到0xffffffffffffffffL范围内的任何值,则结果为NaN。

此外,NaN在API内部进行了逻辑处理。
文档

/**
 * 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;

顺便说一句,NaN作为你的代码示例:

/**
 * 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
你能做的是使用compare/compareTo

Double.NaN被此方法视为等于其自身并且大于所有其他double值(包括Double.POSITIVE_INFINITY)。

Double.compare(Double.NaN, Double.NaN);
Double.NaN.compareTo(Double.NaN);

或者,equals

如果this和argument都表示Double.NaN,则equals方法返回true,即使Double.NaN == Double.NaN的值为false。

Double.NaN.equals(Double.NaN);