2014-05-02 7 views
9

Ich schreibe eine Klasse Vec2D, die einen zweidimensionalen Vektor darstellt. Ich speichere x und y in double s.Bedeutung von Double.doubleToLongBits (x)

Auf die Frage, equals(Object obj zu erzeugen und hashCode() Eclipse dies erzeugt:

@Override 
public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    long temp; 
    temp = Double.doubleToLongBits(x); 
    result = prime * result + (int) (temp^(temp >>> 32)); 
    temp = Double.doubleToLongBits(y); 
    result = prime * result + (int) (temp^(temp >>> 32)); 
    return result; 
} 
@Override 
public boolean equals(Object obj) { 
    if (this == obj) 
     return true; 
    if (obj == null) 
     return false; 
    if (getClass() != obj.getClass()) 
     return false; 
    Vec2D other = (Vec2D) obj; 
    if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) 
     return false; 
    if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) 
     return false; 
    return true; 
} 

Was ist die Bedeutung von Double.doubleToLongBits(x) in diesem Zusammenhang? Kann ich nicht einfach x != other.x schreiben?

Antwort

9

Kurze Antwort: Eklipse verwendet Double.doubleToLongBits, weil das ist, was Double.equals tut:

Das Ergebnis ist true, wenn und nur wenn das Argument nicht null und ist ein Doppel Objekt, das ein doubl e, die das hat repräsentiert gleicher Wert wie double, dargestellt durch dieses Objekt. Zu diesem Zweck werden zwei double Werte als gleich betrachtet, wenn und nur wenn die Methode doubleToLongBits(double) den identischen long Wert zurückgibt, wenn sie auf beide angewendet wird.

Lange Antwort: Die JLS gibt einige Unterschiede zwischen Double.equals und == an. Für eine spezifizierte Differenz in JLS 4.2.3 und JLS 15.21.1:

Positive und negative Null Null zu vergleichen, gleich sind; somit ist das Ergebnis des Ausdrucks 0.0==-0.0true und das Ergebnis 0.0>-0.0 ist false.Aber andere Operationen können positive und negative Null unterscheiden; zum Beispiel hat den Wert positive Unendlichkeit, während der Wert negative Unendlichkeit ist.

Weitere Grüße NaN:

Wenn einer der Operanden NaN ist, dann ist das Ergebnis der ==false sondern das Ergebnis != ist true.

In der Tat ist der Test x!=xtrue wenn und nur wenn der Wert von x NaN ist.

Wie Sie sehen können, es ist möglich, dass zwei Doppel Werte mit == zu vergleichen, sondern tatsächlich einem anderen Verhalten entsprechen, wenn in Mathematik und Hash-Tabellen verwendet. Beim Schreiben einer generierten Gleichheitsmethode macht Eclipse daher die Annahme, dass zwei Doubles nur dann gleich sind, wenn alle Operationen, die mit ihnen durchgeführt werden können, identisch sind oder (äquivalent) wenn sie autoboxiert und mit ihren equals Methoden verglichen werden. Dies ist besonders wichtig, wenn das Umschalten zwischen double und Double-it besonders unerwartet wäre, da die Gleichheitseigenschaften sich dort unterscheiden.

Natürlich können Sie von dieser Annahme abweichen: Unabhängig davon, ob es eine gute Idee ist, können Sie Sonderfälle auf jede der vielen möglichen NaN-Darstellungen zuweisen, in welchem ​​Fall Double.doubleToRawLongBits() wäre eine bessere Übereinstimmung für Ihre equals und hashCode Methoden. Desgleichen könnte Ihr Anwendungsfall Objekte mit +0.0 und -0.0 als äquivalent behandeln und garantieren, dass NaN - Werte nicht möglich sind. In diesem Fall könnte ein roher == - Vergleich für equals besser funktionieren (aber an diesem Punkt dieselben Kriterien für hashCode wird schwierig).

0

Ein kurzer Blick auf die Online-Javadoc- ergibt dies: Liefert

eine Darstellung des angegebenen Gleitkommawert gemäß dem IEEE 754 Gleitkommazahlen „double-Format“ -Bit-Layout.

...

In allen Fällen ist das Ergebnis eine lange Ganzzahl, die, wenn sie auf die longBitsToDouble (long) angegebenen Methode wird ein Fließkommawert gleich dem Argument doubleToLongBits erzeugen (ausgenommen all NaN-Werte werden auf einen einzelnen "kanonischen" NaN-Wert reduziert.

es ist also wahrscheinlich eine Art und Weise zu standardisieren die double Darstellungen von x und y, wie NaN mehrere double Darstellungen

3

Da == und != folgen IEEE-754-Semantik für die Doppel haben, Double.NaN != Double.NaN und 0.0 == -0.0. Dieses Verhalten ist möglicherweise nicht das, was Sie wollen, also wandelt Double.doubleToLongBits() die 64 Bits von double Daten in 64 Bits von long Daten um, so dass Operationen wie Bitverschiebungen und XOR funktionieren. obwohl

Ehrlich gesagt, würde ich sagen, dass die Verwendung von doubleToLongBits ein Fehler hier ist, denn wenn Sie kümmern sich um exakte Gleichheit sollten Sie Double.doubleToRawLongBits() verwenden (was führt keine Übersetzungen auf den double Daten überhaupt) statt.