NaN en Java

NaN en Java

1. Vue d'ensemble

En termes simples,NaN est une valeur de type de données numérique qui signifie «pas un nombre».

Dans ce rapide tutoriel, nous expliquerons la valeurNaN en Java et les différentes opérations qui peuvent produire ou impliquer cette valeur.

2. Qu'est-ce queNaN?

NaN usually indicates the result of invalid operations. Par exemple, tenter de diviser zéro par zéro est l'une de ces opérations.

We also use NaN for unrepresentable values. La racine carrée de -1 est un tel cas, car nous pouvons décrire la valeur (i) uniquement en nombres complexes.

LeIEEE Standard for Floating-Point Arithmetic (IEEE 754) définit la valeur deNaN. In Java, the floating-point types float and double implement this standard.

Java définit les constantesNaN des typesfloat etdouble commeFloat.NaN etDouble.NaN:

«A constant holding a Not-a-Number (NaN) value of type double. It is equivalent to the value returned by Double.longBitsToDouble(0x7ff8000000000000L).”

and:

«Une constante contenant une valeur Not-a-Number (NaN) de type float. Il équivaut à la valeur renvoyée par Float.intBitsToFloat (0x7fc00000). »

Nous n’avons pas ce type de constantes pour d’autres types de données numériques en Java.

3. Comparaisons avecNaN

Lors de l'écriture de méthodes en Java, nous devrions vérifier que l'entrée est valide et dans la plage attendue. La valeur deNaN n'est pas une entrée valide dans la plupart des cas. Par conséquent, nous devons vérifier que la valeur d'entrée n'est pas une valeurNaN et gérer ces valeurs d'entrée de manière appropriée.

NaN ne peut être comparé à aucune valeur de type flottant. Cela signifie que nous obtiendronsfalse pour toutes les opérations de comparaison impliquantNaN (sauf "! =" Pour lequel nous obtenonstrue).

On obtienttrue pour «x != x” si et seulement six estNaN:

System.out.println("NaN == 1 = " + (NAN == 1));
System.out.println("NaN > 1 = " + (NAN > 1));
System.out.println("NaN < 1 = " + (NAN < 1));
System.out.println("NaN != 1 = " + (NAN != 1));
System.out.println("NaN == NaN = " + (NAN == NAN));
System.out.println("NaN > NaN = " + (NAN > NAN));
System.out.println("NaN < NaN = " + (NAN < NAN));
System.out.println("NaN != NaN = " + (NAN != NAN));

Regardons le résultat de l’exécution du code ci-dessus:

NaN == 1 = false
NaN > 1 = false
NaN < 1 = false
NaN != 1 = true
NaN == NaN = false
NaN > NaN = false
NaN < NaN = false
NaN != NaN = true

Par conséquent,we cannot check for NaN by comparing with NaN using “==” or “!= “. En fait, nous devrions rarement utiliser les opérateurs «==» ou «! =» Avec les typesfloat oudouble.

À la place, nous pouvons utiliser l'expression «x ! = x». Cette expression ne renvoie vrai que pourNAN.

Nous pouvons également utiliser les méthodesFloat.isNaN etDouble.isNaN pour vérifier ces valeurs. C'est l'approche préférée car elle est plus lisible et compréhensible:

double x = 1;
System.out.println(x + " is NaN = " + (x != x));
System.out.println(x + " is NaN = " + (Double.isNaN(x)));

x = Double.NaN;
System.out.println(x + " is NaN = " + (x != x));
System.out.println(x + " is NaN = " + (Double.isNaN(x)));

Nous obtiendrons le résultat suivant en exécutant ce code:

1.0 is NaN = false
1.0 is NaN = false
NaN is NaN = true
NaN is NaN = true

4. Opérations produisantNaN

Lorsque vous effectuez des opérations impliquant les typesfloat etdouble, nous devons être conscients des valeursNaN.

Some floating-point methods and operations produce NaN values instead of throwing an Exception. Il se peut que nous devions traiter ces résultats explicitement.

Un cas courant résultant en des valeurs not-a-number estmathematically undefined numerical operations:

double ZERO = 0;
System.out.println("ZERO / ZERO = " + (ZERO / ZERO));
System.out.println("INFINITY - INFINITY = " +
  (Double.POSITIVE_INFINITY - Double.POSITIVE_INFINITY));
System.out.println("INFINITY * ZERO = " + (Double.POSITIVE_INFINITY * ZERO));

Ces exemples donnent le résultat suivant:

ZERO / ZERO = NaN
INFINITY - INFINITY = NaN
INFINITY * ZERO = NaN

Les opérations numériques qui n'ont pas de résultats en nombres réels produisent également desNaN:

System.out.println("SQUARE ROOT OF -1 = " + Math.sqrt(-1));
System.out.println("LOG OF -1 = " +  Math.log(-1));

Ces déclarations entraîneront:

SQUARE ROOT OF -1 = NaN
LOG OF -1 = NaN

Toutes les opérations numériques avecNaN comme opérande produisentNaN comme résultat:

System.out.println("2 + NaN = " +  (2 + Double.NaN));
System.out.println("2 - NaN = " +  (2 - Double.NaN));
System.out.println("2 * NaN = " +  (2 * Double.NaN));
System.out.println("2 / NaN = " +  (2 / Double.NaN));

Et le résultat de ce qui précède est:

2 + NaN = NaN
2 - NaN = NaN
2 * NaN = NaN
2 / NaN = NaN

Enfin, nous ne pouvons pas affecternull aux variables de typedouble oufloat. Au lieu de cela, nous pouvons attribuer explicitementNaN à de telles variables pour indiquer des valeurs manquantes ou inconnues:

double maxValue = Double.NaN;

5. Conclusion

Dans cet article, nous avons discuté deNaN et des différentes opérations qui l'impliquent. Nous avons également discuté de la nécessité de gérer lesNaN tout en effectuant des calculs en virgule flottante en Java de manière explicite.

Le code source complet peut être trouvéover on GitHub.