Pourquoi ne Double.NaN==Double.NaN return false?
Je viens de l'étude de OCPJP questions et j'ai trouvé cet étrange code:
public static void main(String a[]) {
System.out.println(Double.NaN==Double.NaN);
System.out.println(Double.NaN!=Double.NaN);
}
Quand j'ai couru le code, je l'ai eu:
false
true
Comment est la sortie false
lorsque nous comparons deux choses qui se ressemblent les uns que les autres? Ce n' NaN
veux dire?
- C'est vraiment bizarre. Parce Que Double.NaN est statique final, la comparaison avec == doit retourner true. +1 pour la question.
- La même chose est vraie en python:
In [1]: NaN==NaN Out[1]: False
- La même chose est vraie dans toutes les langues de suivre correctement la norme IEEE 754.
- L'Intuition: "Bonjour" n'est pas un nombre, vrai (boolean) n'est pas un nombre. NaN != NaN, pour la même raison "Bonjour" != vrai
- Mais quand je fais Double.comparer(Double.NaN, Double.NaN), je suis 0 en sortie je.e les deux sont égaux
- La comparaison avec
Double.NaN==Double.NaN
convient en effet de retourner vrai siDouble.NaN
étaient de typejava.lang.Double
. Cependant, son type est la primitivedouble
, et l'opérateur règles dedouble
appliquer (ce qui demande cette inégalité pour assurer la conformité avec la norme IEEE 754, comme expliqué dans les réponses). - Oui, c'est en effet un peu incohérent. Cependant, il est explicitement décrite dans la documentation Javadoc: "Double.NaN est considéré par cette méthode pour être égal à lui-même " (voir file:///C:/Users/sle/Downloads/Docs/jdk-6u25-fcs-bin-b04-apidocs-04_Apr_2011/docs/api/java/lang/Double.html#compareTo%28java.lang.Double%29 )
- Voir aussi Pourquoi est indéfini == undefined, mais NaN != NaN? et en fait NaN est égal à NaN (ce sont des propos de JS, mais comme noté au-dessus et au-dessous, c'est indépendant de la langue).
- mais:
String h = "Hello"; // not a number
assertFalse(h != h); // is false
Double.NaN comportement certainement n'est pas intuitif...
Vous devez vous connecter pour publier un commentaire.
NaN signifie "Pas un Nombre".
Java Langage de Spécification (JLS) Troisième Édition dit:
false
. Alors que la norme diffère de Java dans ce IEEE exige que(NAN != NAN) == false
.NaN est, par définition, n'est pas égale à un nombre quelconque, y compris NaN. Cela fait partie de la norme IEEE 754 et mis en œuvre par le CPU/FPU. Il n'est pas quelque chose de la JVM a pour ajouter de la logique à l'appui.
http://en.wikipedia.org/wiki/NaN
Java traite tous NaN tranquille NaN.
Pourquoi cette logique
NaN
signifieNot a Number
. Ce n'est pas un nombre? Quoi que ce soit. Vous pouvez avoir tout dans un côté et rien de l'autre côté, rien ne garantit que les deux sont égaux.NaN
est calculé avecDouble.longBitsToDouble(0x7ff8000000000000L)
et comme vous pouvez le voir dans la documentation delongBitsToDouble
:Aussi,
NaN
est logiquement traités à l'intérieur de l'API.Documentation
Par la voie,
NaN
est testé en tant que votre échantillon de code:Solution
Ce que vous pouvez faire est d'utiliser
compare
/compareTo
:Ou,
equals
:NaN != NaN
être faux aurait de rendre les programmes plus compliqué que d'avoirNaN != NaN
être vrai? Je sais IEEE pris la décision il y a longtemps, mais à partir d'un point de vue pratique, je n'ai jamais vu des cas où c'est utile. Si une opération est censé fonctionner jusqu'à ce que itérations consécutives à donner le même résultat, ayant deux itérations consécutives de rendement NaN serait "naturellement" détecté comme une condition de sortie il n'y avait pas ce comportement.f(f(f...f(x)))
, et l'on retrouve uny=f[n](x)
pour certainsn
tels que le résultat def(y)
est impossible de distinguer lesy
, puisy
sera impossible de distinguer le résultat de tout plus profondément imbriquéef(f(f(...f(y)))
. Même si l'on voulaitNaN==NaN
faux, ayantNan!=Nan
aussi faux serait moins "surprenant" que d'avoirx!=x
être vrai pour certaines valeurs de x.Double.NaN
n'est pasDouble
, maisdouble
, donc la question est celle du comportement dedouble
. Bien qu'il existe des fonctions qui peuvent tester une relation d'équivalence impliquantdouble
valeurs, la seule réponse convaincante je sais de "pourquoi" (qui fait partie de la question d'origine) est "parce que certaines personnes à l'IEEE ne pense pas que l'égalité de l'expérimentation de définir une relation d'équivalence". BTW, est-il concise idiomatiques moyen de testerx
ety
pour l'équivalence à l'aide de seulement primitive-opérateurs? Toutes les formules que je connais sont plutôt maladroit.equals
retournetrue
lorsque l'on compare les deuxNaN
's, c'est qu'il va faire des tables de hachage pour fonctionner correctement.equals
méthode en Java tests six
est supérieur à y, ou si c'est moins de y, et si aucune condition s'applique, il convertit les 64 bits de chaque valeur à unlong
avec le même motif et examine les valeurs résultantes. Pas particulièrement concis. Si l'on accepte positifs et négatifs de zéro, comme équivalent (à mon humble avis, ils ne devraient pas être, mais une définition de l'égalité, qui les considéraient comme équivalent serait au moins une relation d'équivalence),(x >= y && x <= y) || (x != x && y != y)
serait probablement plus rapide à moins qu'une implémentation de Java utilisé une implémentation native.Double.NaN.equals/compareTo
n'est pas un code valide!Double.NaN
est undouble
et vous ne pouvez pas appeler la méthode d'elle.Il pourrait ne pas être une réponse directe à la question.
Mais si vous voulez vérifier si quelque chose est égale à
Double.NaN
vous devez utiliser ce:Ce sera le retour de
true
La javadoc pour le Double.NaN dit tout:
Fait intéressant, la source de
Double
définitNaN
ainsi:Spécial comportement que vous décrivez est câblé dans la JVM.
que par, La norme IEEE pour l'arithmétique à virgule flottante pour les nombres Double Précision,
où,
Ce qui signifie,
Si tous les
E
bits sont à 1, et s'il est non nul peu dansF
le nombre estNaN
.donc, entre autres, tous les numéros suivants sont
NaN
,En particulier, vous ne pouvez pas tester
pour vérifier si le résultat est égal à
Double.NaN
, parce que tous les “pas un nombre”, les valeurs sont considérées comme distinctes. Toutefois, vous pouvez utiliser leDouble.isNaN
méthode:NaN est une valeur spéciale qui indique "pas un nombre"; c'est le résultat de certains invalides opérations arithmétiques, comme
sqrt(-1)
, et a la (parfois ennuyeux) des biens quiNaN != NaN
.Pas un certain nombre représente le résultat des opérations dont le résultat n'est pas représentable par un nombre. Le plus célèbre de l'opération est 0/0, dont le résultat n'est pas connu.
Pour cette raison, NaN n'est pas égal à quoi que ce soit (y compris d'autres pas-un-certain nombre de valeurs). Pour plus d'informations, consultez la page wikipédia: http://en.wikipedia.org/wiki/NaN
0/0
.0/0
est toujours NaN, mais NaN peut être le résultat d'autres opérations telles que2+NaN
:an operation that has no mathematically definite result produces NaN
, que par la réponse par @AdrianMitevSelon cette lien, il a diverses situations et difficile à mémoriser. C'est la façon dont je me souviens et de les distinguer.
NaN
signifie "mathématiquement non définie", par exemple: "le résultat de 0 divisé par 0 n'est pas défini" et parce qu'il n'est pas défini, de sorte que la "comparaison liées à l'indéfini est bien sûr pas défini". En outre, il fonctionne plus comme mathématique locaux. D'autre part, à la fois positifs et négatifs infini est prédéfini et définitive, par exemple "positive ou négative de l'infini grand est bien défini mathématiquement".