Reputation: 41909
Why does this comparison evaluate to true
?
scala> Double.NaN equals java.lang.Double.NaN
res5: Boolean = true
But this one evaluates to false
?
scala> Double.NaN == java.lang.Double.NaN
res6: Boolean = false
aside: this interesting Twitter thread prompted me to ask this question
Upvotes: 12
Views: 5232
Reputation: 6852
This is not about Scala's NaN vs. Java's -- there is only one 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. 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." 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? But given that you did, you are running into the bit of Java weirdness that I.K. pointed us to the docs for. 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???
}
}
Upvotes: 22
Reputation:
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
. Consequently, the equals
method for java.lang.Double
is called. 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.
scala> Double.NaN == java.lang.Double.NaN
res6: Boolean = false
This evaluates to false
because Scala's ==
operator follows the IEEE specification. It does not call down to the Java ==
operator. Also, NaN
is not a number as mentioned by @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.
Upvotes: 2
Reputation: 170723
Double.NaN
is the same as java.lang.Double.NaN
, as AmigoNice already said. It's a Double
(or double
in Java terms). So using ==
on it is the same as ==
in Java and returns false
for two NaNs, as expected. 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).
Upvotes: 3