比较 Scala 和 Java Double.NaN

Posted

技术标签:

【中文标题】比较 Scala 和 Java Double.NaN【英文标题】:Comparing Scala and Java Double.NaN 【发布时间】:2014-06-02 13:08:36 【问题描述】:

为什么这个比较结果是true

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

但是这个结果是false?

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

aside:this 有趣的 Twitter 帖子提示我问了这个问题

【问题讨论】:

它们的值相等,但它们的实例不相等。 @Obicere,您能否扩展您的答案并解释其中哪个运营商在进行参考比较,哪个运营商在进行价值比较? 关于 scala 语言别名的一些讨论:groups.google.com/forum/#!msg/scala-language/LJGpb1wDjI4/… 嘿@AmigoNico。抱歉耽搁了。感谢您的详细解答 没问题,凯文——很高兴它有帮助! 【参考方案1】:

这不是关于 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 中这样做?但鉴于你这样做了,你遇到了 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???
  

【讨论】:

“至于 x.equals(y),好吧,你为什么要那样做?”我不了解 Scala,但在 Java 中,如果您要比较两个 big-D Doubles 的值,您会更好这样做! @AndrewBissell 这可能是 OT,但阅读 two big-D Doubles 听起来很有趣。 @AndrewBissell 是的,但 Scala 不是 Java;在 Scala 中,== 并不总是意味着引用相等,就像在 Java 中那样。 在 Scala 中,对于引用类型(AnyRef 的子类型)== 始终编译为对 LHS equals 方法的调用。引用相等写成eq @RandallSchulz 这并不完全正确,还有一些空值处理。在 Scala 中,null == "not null" 为 false,但 null.equals("not null") 抛出 NullPointerException【参考方案2】:

Double.NaNjava.lang.Double.NaN 相同,正如 AmigoNice 已经说过的那样。这是一个Double(或Java 术语中的double)。因此,在其上使用== 与Java 中的== 相同,并为两个NaN 返回false,正如预期的那样。但是,使用equals 会强制编译器将两边都装箱到java.lang.Double,并且在这种情况下Double.equals 被定义为返回true(我刚刚了解到,这让我很惊讶)。

【讨论】:

在两个NaNs 上使用equals 会导致true 似乎是错误的吗? 它对我有用,因为它与 ==double 不同。【参考方案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,即使根据该值应该是false IEEE 规范。

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

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

【讨论】:

以上是关于比较 Scala 和 Java Double.NaN的主要内容,如果未能解决你的问题,请参考以下文章

Lambda表达式用法大比较: Scala和Java 8

Scala比较器:Ordered与Ordering

《Java8实战》读书笔记13:Java8 与 Scala

《Java8实战》读书笔记13:Java8 与 Scala

Scala安装和开发环境配置教程

Scala安装和开发环境配置教程