Signification de Double.doubleToLongBits (x)

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 pas null et est un object Double qui représente un doubl ayant la même valeur que le double représenté par cet object. À cette fin, deux valeurs double sont considérées comme identiques si et seulement si la méthode doubleToLongBits(double) renvoie la valeur long 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 donc true et le résultat de 0.0>-0.0 est false . 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 valeur 1.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 == est false mais le résultat de != Est true .

En effet, le test x!=x est true 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