2014-04-18 13 views
9

Warum wird dieser Vergleich zu true ausgewertet?Vergleichen von Scala und Java Double.NaN

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

Aber dieser bewertet false?

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

beiseite: this interessant Twitter Thread mich dazu veranlasst, diese Frage zu stellen

+3

Ihr Wert ist gleich, aber ihre Instanz ist nicht. – Obicere

+0

@Obicere, könnten Sie Ihre Antwort erweitern und erläutern, welcher dieser Operatoren den Referenzvergleich durchführt und welcher den Wertevergleich durchführt? –

+0

Einige Diskussionen dazu auf dem Alias ​​scala-Sprache: https://groups.google.com/forum/#!msg/scala-Sprache/LJGpb1wDjI4/HgE8jcGbL0YJ – AmigoNico

Antwort

17

Es geht nicht um Scala NaN vs. Java - es gibt nur eine NaN:

scala> val a = Double.NaN 
a: Double = NaN 

scala> val b = java.lang.Double.NaN 
b: Double = NaN 

Auch ist es nicht dass es zwei Objekte mit dem gleichen Wert gibt. Es ist ungefähr the definition of NaN. Zwei NaNs sind nicht ==, denn so ist NaN definiert - es ist keine Zahl, sondern ein spezieller Wert, der "undefined" bedeutet. Wenn du zwei davon hast, wie würdest du wissen, ob sie gleich sind? Zum Beispiel:

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 

Glücklicherweise sind sie nicht ==; Sie sind keine Zahlen, deren Werte Sie vergleichen können.

Wie für x.equals(y), nun, warum würden Sie das in Scala tun? Aber da du es getan hast, rennst du in die seltsame Java-Verrücktheit, die ich kenne. wies uns auf the docs für. Lassen Sie uns zeigen es:

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

"Wie für x.equals (y), nun, warum würdest du das tun?" Ich weiß nichts über Scala, aber in Java, wenn Sie den Wert von zwei großen 'Double' vergleichen, würden Sie * besser * das tun! –

+2

@AndrewBissell dies kann OT sein, aber das Lesen von 'zwei Big-D-Doubles' klang einfach so lustig. – Obicere

+0

@AndrewBissell Ja, aber Scala ist nicht Java; in Scala bedeutet '=' nicht immer Referenzgleichheit, wie es in Java der Fall ist. – Jesper

2

Double.NaN die gleiche wie java.lang.Double.NaN ist, wie schon gesagt, AmigoNice. Es ist ein Double (oder double in Java-Begriffen). Also == auf es ist das gleiche wie == in Java und gibt false für zwei NaNs, wie erwartet. Die Verwendung von equals zwingt den Compiler jedoch, beide Seiten auf java.lang.Double zu boxen, und Double.equals ist definiert, in diesem Fall true zurückzugeben (was ich gerade gelernt habe und was mich überrascht hat).

+0

scheint es falsch zu sein, dass die Verwendung von 'equals' auf zwei' NaN's in 'true' resultiert? –

+0

Es tut mir, da es ein Unterschied von '==' für 'double' ist. –

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

Diese wertet zu true weil Double.NaN zu java.lang.Double.NaN entspricht. Folglich wird die equals Methode für java.lang.Double genannt. Entsprechend dem Java documentation, für zwei doubles, d1 und d2, wenn d1 und d2 beide Double.NaN darstellen, dann gibt die equals Methode true zurück, obwohl der Wert false gemäß IEEE-Spezifikation sein sollte.

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

Dies wertet zu false weil Scala == Bediener die IEEE-Spezifikation folgt. Es ruft den Java-Operator == nicht auf. Auch ist NaN keine Nummer wie von @AmigoNico erwähnt. Es ist ein Platzhalter für eine große Anzahl von "ungültigen" Werten. Es gibt keine Möglichkeit zu wissen, ob zwei NaN gleich sind, weil sie durch zwei verschiedene "ungültige" Werte repräsentiert werden könnten.

Verwandte Themen