比较Scala和Java Double.NaN

时间:2014-04-18 03:50:30

标签: java scala nan

为什么此比较会评估为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帖子促使我提出这个问题

3 个答案:

答案 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)

AmigoNice已经说过,

Double.NaNjava.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是否相等,因为它们可以由两个不同的“无效”值表示。