web-dev-qa-db-fra.com

Pourquoi Double.NaN == Double.NaN renvoie-t-il false?

J'étudiais juste les questions de l'OCPJP 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 exécuté le code, j'ai eu:

false
true

Comment la sortie false lorsque nous comparons deux éléments qui se ressemblent? Que signifie NaN?

148
Maverick

NaN signifie "pas un nombre".

La troisième édition de la spécification du langage Java (JLS) dit :

Une opération qui déborde génère un infini signé, une opération qui déborde génère une valeur dénormalisée ou un zéro signé et une opération qui n’a pas de résultat mathématiquement défini produit NaN. En conséquence, toutes les opérations numériques avec NaN en tant qu'opérande produisent NaN. Comme cela a déjà été décrit, NaN n'est pas ordonné. Par conséquent, une opération de comparaison numérique impliquant un ou deux NaNs renvoie false et toute comparaison != impliquant NaN renvoie true, y compris x!=x lorsque x est NaN.

134
Adrian Mitev

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 la CPU/FPU. La JVM n’a pas à ajouter de logique à prendre en charge.

http://en.wikipedia.org/wiki/NaN

Une comparaison avec un NaN renvoie toujours un résultat non ordonné, même en comparant avec lui-même. ... Les prédicats d'égalité et d'inégalité ne signalant pas, x = x retournant false peut être utilisé pour tester si x est un NaN silencieux. 

Java traite tous les NaN comme des NaN silencieux.

60
Peter Lawrey

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 côté, donc rien ne garantit que les deux sont égaux. NaN est calculé avec Double.longBitsToDouble(0x7ff8000000000000L) et, comme vous pouvez le constater dans la documentation de longBitsToDouble:

Si l'argument est une valeur comprise entre 0x7ff0000000000001L et 0x7fffffffffffffffL ou dans la plage 0xfff0000000000001L à 0xffffffffffffffffL, le résultat est une NaN.

De plus, NaN est traité logiquement à l'intérieur de 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, NaNis a été testé comme exemple 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 est d'utiliser compare/compareTo:

Double.NaN est considéré par cette méthode comme étant égal à lui-même et supérieur à toutes les autres valeurs double (y compris Double.POSITIVE_INFINITY).

Double.compare(Double.NaN, Double.NaN);
Double.NaN.compareTo(Double.NaN);

Ou equals:

Si this et argument représentent tous deux Double.NaN, alors la méthode equals renvoie true, même si Double.NaN==Double.NaN a la valeur false.

Double.NaN.equals(Double.NaN);
48
falsarella

Ce n'est peut-être pas une réponse directe à la question . Mais si vous voulez vérifier si quelque chose vaut Double.NaN, vous devriez utiliser ceci:

double d = Double.NaN
Double.isNaN(d);

Cela retournera true

11
JREN

Le javadoc pour Double.NaN dit tout:

Une constante contenant une valeur de type double (NaN) non notée Cela équivaut à la valeur renvoyée par Double.longBitsToDouble(0x7ff8000000000000L).

Fait intéressant, la source de Double définit NaN ainsi:

public static final double NaN = 0.0d / 0.0;

Le comportement spécial que vous décrivez est câblé dans la machine virtuelle Java.

6
Bohemian

NaN est une valeur spéciale qui indique "pas un nombre"; il résulte de certaines opérations arithmétiques non valides, telles que sqrt(-1), et possède la propriété (parfois gênante) qui NaN != NaN.

3
Fred Foo

selon, La norme IEEE pour l’arithmétique en virgule flottante pour les nombres à double précision,

Représentation standard à virgule flottante double précision IEEE nécessite un mot de 64 bits, qui peut être représenté par un numéro numéroté de 0 à 63, de gauche à droite

enter image description hereoù,

S: Sign – 1 bit
E: Exponent – 11 bits
F: Fraction – 52 bits 

Si E=2047 (tous les E sont 1) et que F est différent de zéro, alors V=NaN ("Pas un nombre")

Ce qui signifie,

Si tous les bits E sont à 1 et s'il existe un bit différent de zéro dans F, le nombre est NaN

par conséquent, entre autres, tous les nombres suivants sont NaN,

0 11111111 0000000000000000010000000000000000000000000000000000 = NaN
1 11111111 0000010000000000010001000000000000001000000000000000 = NaN
1 11111111 0000010000011000010001000000000000001000000000000000 = NaN

En particulier, vous ne pouvez pas tester 

if (x == Double.NaN) 

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 la méthode Double.isNaN:

if (Double.isNaN(x)) // check whether x is "not a number"
3
Sufiyan Ghori

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 non numériques). Pour plus d’informations, consultez la page wikipedia: http://en.wikipedia.org/wiki/NaN

2
Matteo

Selon ce lien , il a des situations diverses et difficiles à retenir. C'est comme ça que je me souviens et les distingue. NaN signifie "mathématiquement indéfini", par exemple: "le résultat de 0 divisé par 0 est indéfini" et comme il est indéfini, la comparaison avec indéfini 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 positif positif ou négatif est mathématiquement bien défini". 

0
Tiina