J'étudiais juste les questions OCPJP et j'ai trouvé ce code étrange:
public static void main(String a[]) {
System.out.println(Double.NaN==Double.NaN);
System.out.println(Double.NaN!=Double.NaN);
}
Quand j'ai exécuté le code, j'ai obtenu:
false
true
Comment est le résultat false
lorsque nous comparons deux choses qui se ressemblent? Que veut NaN
dire?
In [1]: NaN==NaN Out[1]: False
Double.NaN==Double.NaN
devrait en effet retourner true si ellesDouble.NaN
étaient de typejava.lang.Double
. Cependant, son type est le primitifdouble
, et les règles d'opérateur pourdouble
s'appliquent (qui exigent cette inégalité pour se conformer à IEEE 754, comme expliqué dans les réponses).Réponses:
NaN signifie "Pas un nombre".
La troisième édition de Java Language Specification (JLS) dit :
la source
false
. Cette norme diffère donc de Java en ce que l'IEEE l'exige(NAN != NAN) == false
.NaN n'est par définition égal à aucun nombre, y compris NaN. Cela fait partie de la norme IEEE 754 et est implémenté par le CPU / FPU. Ce n'est pas quelque chose que la JVM doit ajouter de logique à prendre en charge.
http://en.wikipedia.org/wiki/NaN
Java traite tous les NaN comme des NaN silencieux.
la source
Pourquoi cette logique
NaN
signifieNot a Number
. Qu'est-ce qui n'est pas un nombre? N'importe quoi. Vous pouvez avoir n'importe quoi d'un côté et n'importe quoi de l'autre côté, donc rien ne garantit que les deux sont égaux.NaN
est calculé avecDouble.longBitsToDouble(0x7ff8000000000000L)
et comme vous pouvez le voir dans la documentation delongBitsToDouble
:En outre,
NaN
est traité logiquement à l'intérieur de l'API.Documentation
En passant,
NaN
est testé comme exemple de code:Solution
Ce que vous pouvez faire, c'est utiliser
compare
/compareTo
:Ou,
equals
:la source
NaN != NaN
été faux rendrait les programmes plus compliqués que d'avoirNaN != NaN
été vrai? Je sais que l'IEEE a pris la décision il y a longtemps, mais d'un point de vue pratique, je n'ai jamais vu de cas où cela est utile. Si une opération est supposée s'exécuter jusqu'à ce que des itérations consécutives donnent le même résultat, le fait d'avoir deux itérations consécutives produisant NaN serait "naturellement" détecté comme une condition de sortie sans ce comportement.f(f(f...f(x)))
, et que l'on trouve uny=f[n](x)
pour certainsn
tel que le résultat def(y)
est indiscernabley
, alorsy
il sera impossible de le distinguer du résultat de tout plus profondément imbriquéf(f(f(...f(y)))
. Même si l'on voulaitNaN==NaN
être faux, avoirNan!=Nan
également été faux serait moins "surprenant" que d'avoirx!=x
été vrai pour certains x.Double.NaN
n'est pasDouble
, maisdouble
, donc la question est liée au comportement dedouble
. Bien qu'il existe des fonctions qui peuvent tester une relation d'équivalence impliquant desdouble
valeurs, la seule réponse convaincante que je connaisse pour «pourquoi» (qui fait partie de la question initiale) est «parce que certaines personnes à l'IEEE ne pensaient pas que les tests d'égalité devraient définir une relation d'équivalence ". BTW, existe-t-il un moyen idiomatique concis de testerx
ety
d'équivalence en utilisant uniquement des opérateurs primitifs? Toutes les formulations que je connais sont plutôt maladroites.Ce n'est peut-être pas une réponse directe à la question. Mais si vous voulez vérifier si quelque chose est égal à,
Double.NaN
vous devez utiliser ceci:Cela reviendra
true
la source
Le javadoc pour Double.NaN dit tout:
Fait intéressant, la source de
Double
définitNaN
ainsi:Le comportement spécial que vous décrivez est câblé dans la JVM.
la source
selon, 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 y a un bit différent de zéro,F
le nombre estNaN
.par conséquent, entre autres, tous les nombres suivants sont
NaN
,En particulier, vous ne pouvez pas tester
pour vérifier si un résultat particulier est égal
Double.NaN
, car toutes les valeurs «pas un nombre» sont considérées comme distinctes. Cependant, vous pouvez utiliser laDouble.isNaN
méthode:la source
NaN est une valeur spéciale qui indique "pas un nombre"; c'est le résultat de certaines opérations arithmétiques invalides, telles que
sqrt(-1)
, et possède la propriété (parfois ennuyeuse) quiNaN != NaN
.la source
Pas un nombre représente le résultat d'opérations dont le résultat n'est pas représentable par un nombre. L'opération la plus connue est 0/0, dont le résultat n'est pas connu.
Pour cette raison, NaN n'est égal à rien (y compris les autres valeurs not-a-number). Pour plus d'informations, il suffit de consulter la page wikipedia: http://en.wikipedia.org/wiki/NaN
la source
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
, selon la réponse par @AdrianMitevSelon ce lien , il y a des situations diverses et difficiles à retenir. C'est ainsi que je me souviens et je les distingue.
NaN
signifie "mathématiquement indéfini" par exemple: "le résultat de 0 divisé par 0 est indéfini" et parce qu'il n'est pas défini, donc "la comparaison liée à undefined est bien sûr indéfinie". En outre, cela fonctionne plus comme des prémisses mathématiques. D'autre part, l'infini positif et négatif est prédéfini et définitif, par exemple "l'infini grand positif ou négatif est bien défini mathématiquement".la source