Pourquoi cette logique
NaN
signifie Not a Number
. Qu'est-ce qui n'est pas un nombre ? N'importe quoi. Vous pouvez avoir n'importe quoi dans un côté et n'importe quoi dans l'autre, donc rien ne garantit que les deux sont égaux. NaN
est calculé avec Double.longBitsToDouble(0x7ff8000000000000L)
et comme vous pouvez le voir dans la documentation de longBitsToDouble
:
Si l'argument est une valeur quelconque dans la plage 0x7ff0000000000001L
par le biais de 0x7fffffffffffffffL
ou dans l'intervalle 0xfff0000000000001L
par le biais de 0xffffffffffffffffL
le résultat est un NaN
.
Aussi, NaN
est traitée logiquement dans l'API.
Documentation
/**
* A constant holding a Not-a-Number (NaN) value of type
* {@code double}. It is equivalent to the value returned by
* {@code Double.longBitsToDouble(0x7ff8000000000000L)}.
*/
public static final double NaN = 0.0d / 0.0;
Au fait, NaN
est testé comme votre échantillon de code :
/**
* Returns {@code true} if the specified number is a
* Not-a-Number (NaN) value, {@code false} otherwise.
*
* @param v the value to be tested.
* @return {@code true} if the value of the argument is NaN;
* {@code false} otherwise.
*/
static public boolean isNaN(double v) {
return (v != v);
}
Solution
Ce que vous pouvez faire, c'est utiliser compare
/ compareTo
:
Double.NaN
est considéré par cette méthode comme étant égal à lui-même et supérieur à tous les autres double
(y compris Double.POSITIVE_INFINITY
).
Double.compare(Double.NaN, Double.NaN);
Double.NaN.compareTo(Double.NaN);
Ou, equals
:
Si this
et argument
les deux représentent Double.NaN
alors le site equals
La méthode retourne true
même si Double.NaN==Double.NaN
a la valeur false
.
Double.NaN.equals(Double.NaN);
8 votes
C'est vraiment bizarre. Parce que Double.NaN est static final, la comparaison avec == devrait retourner vrai. +1 pour la question.
2 votes
Il en va de même en python :
In [1]: NaN==NaN Out[1]: False
58 votes
Il en va de même dans toutes les langues qui suivent correctement la norme IEEE 754.
4 votes
Intuition : "Hello" n'est pas un nombre, true (booléen) n'est pas non plus un nombre. NaN != NaN pour la même raison que "Bonjour" != vrai
0 votes
@kevin Mais lorsque je fais Double.compare(Double.NaN, Double.NaN), j'obtiens 0 comme résultat, c'est-à-dire que les deux sont égaux.
3 votes
@Stephan : La comparaison avec
Double.NaN==Double.NaN
devrait en effet retourner vrai siDouble.NaN
étaient de typejava.lang.Double
. Cependant, son type est la primitivedouble
et les règles de l'opérateur pourdouble
appliquent (qui exigent cette inégalité pour la conformité avec IEEE 754, comme expliqué dans les réponses).0 votes
@RaviKumar : Oui, c'est en effet un peu incohérent. Cependant, c'est explicitement documenté dans les Javadocs : "Double.NaN est considéré par cette méthode comme étant é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 ).
0 votes
Voir aussi Pourquoi undefined == undefined mais NaN != NaN ? et est NaN égale à NaN (il s'agit de JS, mais comme indiqué ci-dessus et ci-dessous, ceci est indépendant du langage).
0 votes
@Kevin mais :
String h = "Hello"; // not a number
assertFalse(h != h); // is false
Le comportement de Double.NaN n'est certainement pas intuitif...