有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

比较Scala和Java Double。楠

为什么这个比较的结果是true

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

但是这个计算结果是false

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

旁白:this有趣的推特帖子促使我问这个问题


共 (3) 个答案

  1. # 1 楼答案

    这不是Scala的NaN与Java的NaN之争,只有一个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的怪诞,这是I.K.给我们指出的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???
      }
    }
    
  2. # 2 楼答案

    正如AmigoNice已经说过的那样,{}与{}是相同的。它是一个Double(或者用Java术语来说是double)。因此,在其上使用==与Java中的==相同,并返回两个NAN的false,如预期的那样。但是,使用equals会强制编译器将两边都框到java.lang.Double,并且Double.equals被定义为在本例中返回true(这是我刚刚学到的,让我感到惊讶)

  3. # 3 楼答案

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

    这计算为true,因为Double.NaN等价于java.lang.Double.NaN。因此,调用java.lang.Doubleequals方法。根据Java documentation,对于两个doubles,d1和d2,如果d1和d2都表示Double.NaN,那么equals方法返回true,即使根据IEEE规范,值应该是false

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

    这计算为false,因为Scala的==操作符遵循IEEE规范。它不调用Java ==操作符。另外,NaN不是@AmigoNico提到的数字。它是大量“无效”值的占位符。无法知道两个NaN是否相等,因为它们可能由两个不同的“无效”值表示