简体   繁体   English

比较Scala和Java Double.NaN

[英]Comparing Scala and Java Double.NaN

Why does this comparison evaluate to true ? 为什么这种比较评估为true

scala> Double.NaN equals java.lang.Double.NaN
res5: Boolean = true

But this one evaluates to false ? 但是这个评估为false

scala> Double.NaN == java.lang.Double.NaN
res6: Boolean = false

aside: this interesting Twitter thread prompted me to ask this question 除此之外: 这个有趣的Twitter帖子促使我提出这个问题

This is not about Scala's NaN vs. Java's -- there is only one NaN: 这不是关于Scala的NaN与Java的关系 - 只有一个NaN:

scala> val a = Double.NaN
a: Double = NaN

scala> val b = java.lang.Double.NaN
b: Double = NaN

Nor is it about there being two objects with the same value. 也不是有两个具有相同价值的物体。 It's about the definition of NaN . 这是关于NaN的定义 Two NaNs are not == because that's the way NaN is defined -- it is not a number , but rather a special value that means "undefined." 两个NaN不是==因为这是定义NaN的方式 - 它不是数字 ,而是一个特殊值,意思是“未定义”。 If you have two of those, how would you know whether they are equal? 如果你有两个,你怎么知道他们是否平等? For example: 例如:

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

Fortunately they are not ==; 幸运的是他们不是==; they are not numbers whose values you can compare. 它们不是可以比较其值的数字。

As for x.equals(y) , well, why would you do that in Scala? 至于x.equals(y) ,那你为什么要在Scala中做到这一点? But given that you did, you are running into the bit of Java weirdness that IK pointed us to the docs for. 但鉴于你做到了,你正在遇到IK向我们指出文档的Java古怪。 Let's demonstrate it: 让我们来证明一下:

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???
  }
}

Double.NaN is the same as java.lang.Double.NaN , as AmigoNice already said. Double.NaN相同java.lang.Double.NaN ,如AmigoNice已经说了。 It's a Double (or double in Java terms). 它是Double (或Java术语的double )。 So using == on it is the same as == in Java and returns false for two NaNs, as expected. 所以在它上面使用==与Java中的==相同,并且如预期的那样为两个NaN返回false However, using equals forces the compiler to box both sides to java.lang.Double , and Double.equals is defined to return true in this case (which I just learned and which surprised me). 但是,使用equals强制编译器将两边都Double.equalsjava.lang.Double ,并且Double.equals被定义为在这种情况下返回true (我刚刚学到了这些并且让我感到惊讶)。

scala> Double.NaN equals java.lang.Double.NaN
res5: Boolean = true

This evaluates to true because Double.NaN is equivalent to java.lang.Double.NaN . 这个计算结果为true因为Double.NaN等同于java.lang.Double.NaN Consequently, the equals method for java.lang.Double is called. 因此,调用java.lang.Doubleequals方法。 According to the Java documentation , for two doubles , d1 and d2, if d1 and d2 both represent Double.NaN , then the equals method returns true , even though the value should be false according to IEEE specification. 根据Java 文档 ,对于两个doubles d1和d2,如果d1和d2都表示Double.NaN ,则equals方法返回true ,即使根据IEEE规范该值应为false

scala> Double.NaN == java.lang.Double.NaN
res6: Boolean = false

This evaluates to false because Scala's == operator follows the IEEE specification. 由于Scala的==运算符遵循IEEE规范,因此计算结果为false It does not call down to the Java == operator. 它不会调用Java ==运算符。 Also, NaN is not a number as mentioned by @AmigoNico. 此外, NaN不是@AmigoNico提到的数字。 It is a place holder for a large number of "invalid" values. 它是大量“无效”值的占位符。 There is no way of knowing whether two NaN's are equal, because they could be represented by two different "invalid" values. 无法知道两个NaN是否相等,因为它们可以用两个不同的“无效”值表示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM