我正在研究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
是什么意思?
答案 0 :(得分:136)
NaN表示“不是数字”。
Java Language Specification (JLS) Third Edition says:
溢出的操作产生有符号的无穷大,下溢的操作产生非规范化值或有符号零,并且没有数学定义结果的操作产生NaN。以NaN作为操作数的所有数值运算都会产生NaN。正如已经描述的那样,NaN是无序的,因此涉及一个或两个NaN的数字比较操作返回
false
,并且涉及NaN的任何!=
比较返回true
,包括x!=x
时x
是NaN。
答案 1 :(得分:60)
NaN根据定义不等于包括NaN在内的任何数字。这是IEEE 754标准的一部分,由CPU / FPU实现。这不是JVM必须添加任何逻辑来支持的。
http://en.wikipedia.org/wiki/NaN
与NaN进行比较时,即使与自身进行比较,也会返回无序结果。 ...相等和不等式谓词是非信令的,因此x = x返回false可用于测试x是否是安静的NaN。
Java将所有NaN视为安静的NaN。
答案 2 :(得分:48)
为何选择逻辑
NaN
表示Not a Number
。什么不是数字?任何东西。你可以在一边拥有任何东西,在另一边拥有任何东西,所以没有什么可以保证两者都是平等的。 NaN
使用Double.longBitsToDouble(0x7ff8000000000000L)
进行计算,您可以在longBitsToDouble
的文档中看到:
如果参数是范围
0x7ff0000000000001L
到的任何值0x7fffffffffffffffL
或0xfff0000000000001L
至0xffffffffffffffffL
范围内NaN
,结果为NaN
。
此外,/**
* 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;
在API内部进行了逻辑处理。
<强>文档强>
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);
}
作为代码示例进行了测试:
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);
。
{{1}}
答案 3 :(得分:14)
这可能不是问题的直接答案。
但是如果你想检查一下是否等于Double.NaN
,你应该使用它:
double d = Double.NaN
Double.isNaN(d);
这将返回true
答案 4 :(得分:6)
javadoc for Double.NaN说明了一切:
保持类型
double
的非数字(NaN)值的常量。它等同于Double.longBitsToDouble(0x7ff8000000000000L)
返回的值。
有趣的是,Double
的来源定义了NaN
:
public static final double NaN = 0.0d / 0.0;
您描述的特殊行为已硬连接到JVM中。
答案 5 :(得分:3)
NaN是一个特殊值,表示“不是数字”;它是某些无效算术运算的结果,例如sqrt(-1)
,并且具有NaN != NaN
的(有时令人讨厌的)属性。
答案 6 :(得分:3)
,双精度数字的The IEEE standard for floating point arithmetic,
IEEE双精度浮点标准表示 需要64位字,可以表示为从0到0的编号 63,从左到右
其中,
S: Sign – 1 bit
E: Exponent – 11 bits
F: Fraction – 52 bits
如果
E=2047
(所有E
为1
)且F
非零,则V=NaN
(“非数字”)
这意味着,
如果所有E
位都为1,并且F
中有任何非零位,则该数字为NaN
。
因此,除其他外,以下所有数字均为NaN
,
0 11111111 0000000000000000010000000000000000000000000000000000 = NaN
1 11111111 0000010000000000010001000000000000001000000000000000 = NaN
1 11111111 0000010000011000010001000000000000001000000000000000 = NaN
特别是,你无法测试
if (x == Double.NaN)
检查特定结果是否等于Double.NaN
,因为所有“非数字”值都被视为不同。但是,您可以使用Double.isNaN
方法:
if (Double.isNaN(x)) // check whether x is "not a number"
答案 7 :(得分:2)
不是数字表示结果无法用数字表示的操作的结果。最着名的操作是0/0,其结果未知。
因此,NaN不等于任何东西(包括其他非数字值)。有关详细信息,请查看维基百科页面:http://en.wikipedia.org/wiki/NaN
答案 8 :(得分:0)
根据这个link,它有各种各样的情况,很难记住。这就是我记忆和区分它们的方式。 NaN
表示&#34;数学上未定义&#34;例如:&#34; 0除以0的结果未定义&#34;因为它是未定义的,所以&#34;与undefined相关的比较当然是未定义的&#34;。此外,它更像是数学前提。另一方面,正和负无限都是预定义的和确定的,例如&#34;正或负无限大是数学上明确定义的#34;。
答案 9 :(得分:0)
如果你有变量
Double a = Double.NaN
使用
String.valueOf(Double.NaN) == a.toString()