为什么此比较会评估为true
?
scala> Double.NaN equals java.lang.Double.NaN
res5: Boolean = true
但是这个评估为false
?
scala> Double.NaN == java.lang.Double.NaN
res6: Boolean = false
除此之外:this有趣的Twitter帖子促使我提出这个问题
答案 0 :(得分:20)
这不是关于Scala的NaN与Java的关系 - 只有一个NaN:
scala> val a = Double.NaN
a: Double = NaN
scala> val b = java.lang.Double.NaN
b: Double = NaN
也不存在两个具有相同值的对象。它是关于the definition of NaN的。两个NaN不是==因为NaN的定义方式是 - 不是数字,而是一个特殊的值,意味着"未定义。"如果你有两个,你怎么知道他们是否平等?例如:
scala> val x = 0.0 / 0.0
x: Double = NaN
scala> val y = Math.sqrt(-1)
y: Double = NaN
scala> x == y
res9: Boolean = false
幸运的是他们不是==;它们不是可以比较其值的数字。
至于x.equals(y)
,那你为什么要在Scala中这样做呢?但鉴于你做到了,你正在遇到一些Java古怪的问题。我们指出the docs。让我们来证明一下:
public class Foo {
public static void main( String[] args ) {
double nan1 = 0.0 / 0.0; Double box1 = nan1;
double nan2 = Math.sqrt(-1); Double box2 = nan2;
System.out.println( nan1 == nan2 ); // false, as expected
System.out.println( box1.equals(box2) ); // true -- WTF???
}
}
答案 1 :(得分:3)
Double.NaN
与java.lang.Double.NaN
相同。它是Double
(或Java术语中的double
)。因此,使用==
与Java中的==
相同,并按预期返回false
两个NaN。但是,使用equals
强制编译器将两边都封装到java.lang.Double
,并且Double.equals
被定义为在这种情况下返回true
(我刚学到这些并且让我感到惊讶)
答案 2 :(得分:2)
scala> Double.NaN equals java.lang.Double.NaN
res5: Boolean = true
此评估结果为true
,因为Double.NaN
相当于java.lang.Double.NaN
。因此,调用equals
的{{1}}方法。根据Java documentation,对于两个java.lang.Double
,d1和d2,如果d1和d2都代表doubles
,则Double.NaN
方法返回equals
,甚至虽然根据IEEE规范,该值应为true
。
false
这评估为scala> Double.NaN == java.lang.Double.NaN
res6: Boolean = false
,因为Scala的false
运算符遵循IEEE规范。它不会调用Java ==
运算符。此外,==
不是@AmigoNico提到的数字。它是大量“无效”值的占位符。无法知道两个NaN是否相等,因为它们可以由两个不同的“无效”值表示。