Vec2D
une classe Vec2D
, représentant un vecteur à 2 dimensions. Je stocke x
et y
en double
s.
Quand on lui a demandé de générer equals(Object obj
et hashCode()
, eclipse a généré ceci:
@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; }
Quelle est la signification de Double.doubleToLongBits(x)
dans ce contexte? Puis-je simplement écrire x != other.x
?
Réponse courte: Eclipse utilise Double.doubleToLongBits parce que c’est ce que fait Double.equals :
Le résultat est
true
si et seulement si l’argument n’est pasnull
et est un object Double qui représente undoubl
ayant la même valeur que ledouble
représenté par cet object. À cette fin, deux valeursdouble
sont considérées comme identiques si et seulement si la méthodedoubleToLongBits(double)
renvoie la valeurlong
identique lorsqu’elle est appliquée à chacune.
Réponse longue: le JLS spécifie quelques différences entre Double.equals et ==. Pour une différence spécifiée dans JLS 4.2.3 et JLS 15.21.1 :
Le zéro positif et le zéro négatif sont égaux. le résultat de l’expression
0.0==-0.0
est donctrue
et le résultat de0.0>-0.0
estfalse
. Mais d’autres opérations peuvent distinguer le zéro positif du négatif; Par exemple,1.0/0.0
a la valeur infini positive, tandis que la valeur1.0/-0.0
est l’infini négatif.
Un autre égard NaN
:
Si l’un des opérandes est NaN, alors le résultat de
==
estfalse
mais le résultat de!=
Esttrue
.En effet, le test
x!=x
esttrue
si et seulement si la valeur de x est NaN.
Comme vous pouvez le constater, il est possible de comparer deux valeurs doubles avec ==
mais correspond en réalité à un comportement différent lorsqu’il est utilisé dans les tables de mathématiques et de hachage . Ainsi, lors de l’écriture d’une méthode d’égalité générée, Eclipse suppose que deux doubles ne sont égaux que si et seulement si toutes les opérations pouvant être effectuées sont identiques ou (de manière équivalente) si elles ont été cochées automatiquement et comparées à leurs méthodes equals
. Ceci est particulièrement important si la commutation entre double
et Double
est particulièrement inattendue pour que les propriétés d’égalité y diffèrent.
Bien sûr, vous pouvez vous écarter de cette hypothèse: que ce soit une bonne idée ou non, vous pouvez affecter des cas particuliers à l’une des nombreuses représentations NaN possibles, auquel cas Double.doubleToRawLongBits()
conviendrait mieux à votre méthodes equals
et hashCode
. De la même façon, votre cas d’utilisation peut traiter les objects avec +0.0 et -0.0 comme équivalents et garantir que les valeurs NaN ne sont pas possibles, auquel cas une comparaison brute ==
peut mieux fonctionner à equals
(mais à quel point imiter les mêmes critères pour hashCode
devient difficile).
Parce que ==
et !=
Double.NaN != Double.NaN
sémantique IEEE-754 pour les doubles, Double.NaN != Double.NaN
et 0.0 == -0.0
. Ces comportements ne sont peut-être pas ce que vous souhaitez, aussi Double.doubleToLongBits()
convertit les 64 bits de données double
en 64 bits de données long
afin que les opérations telles que les décalages de bits et XOR fonctionnent.
Honnêtement, cependant, je dirais que l’utilisation de doubleToLongBits
est un bogue, car si vous tenez à l’égalité exacte, vous devriez utiliser Double.doubleToRawLongBits()
(qui ne réalise aucune traduction sur les données double
).
Un rapide coup d’œil sur le javadoc en ligne donne ceci:
Renvoie une représentation de la valeur en virgule flottante spécifiée conformément à la structure de bits “double format” à virgule flottante IEEE 754.
…
Dans tous les cas, le résultat est un entier long qui, lorsqu’il est atsortingbué à la méthode longBitsToDouble (long), produira une valeur à virgule flottante identique à l’argument de doubleToLongBits (sauf que toutes les valeurs NaN sont réduites à un seul NaN “canonique” valeur).
C’est donc probablement un moyen de normaliser les double
représentations de x
et y
, NaN pouvant avoir plusieurs double
représentations