比较 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-DDouble
s 的值,您会更好这样做!
@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.NaN
与 java.lang.Double.NaN
相同,正如 AmigoNice 已经说过的那样。这是一个Double
(或Java 术语中的double
)。因此,在其上使用==
与Java 中的==
相同,并为两个NaN 返回false
,正如预期的那样。但是,使用equals
会强制编译器将两边都装箱到java.lang.Double
,并且在这种情况下Double.equals
被定义为返回true
(我刚刚了解到,这让我很惊讶)。
【讨论】:
在两个NaN
s 上使用equals
会导致true
似乎是错误的吗?
它对我有用,因为它与 ==
的 double
不同。【参考方案3】:
scala> Double.NaN equals java.lang.Double.NaN
res5: Boolean = true
计算结果为true
,因为Double.NaN
等价于java.lang.Double.NaN
。因此,将调用 java.lang.Double
的 equals
方法。根据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的主要内容,如果未能解决你的问题,请参考以下文章