CodeGym /Blog Java /Random-FR /NaN en Java
Auteur
Oleksandr Miadelets
Head of Developers Team at CodeGym

NaN en Java

Publié dans le groupe Random-FR
En Java, "NaN" signifie "Pas un nombre". Ce n'est pas un type d'exception, plutôt étonnamment, le type de données de NaN est aussi un nombre. Mais souvent, lorsque les programmeurs novices l'obtiennent par inadvertance, ils l'utilisent davantage dans leurs calculs. Par conséquent, les types de données incompatibles en Java lorsqu'ils sont utilisés ensemble peuvent provoquer une erreur pouvant être déclenchée. Il est également courant de voir qu'il java.lang.ArithmeticException: / by zeroest considéré comme identique à NaN. Cependant, Java les traite tous les deux différemment. Assez déroutant? Pour votre compréhension globale, nous allons disséquer en quoi ils sont différents les uns des autres. À la fin de cet article, vous découvrirez les opérations possibles produisant pas un nombre (nan) et quelques moyens simples de les gérer.

Qu'est-ce que NaN ?

Alors, qu'est-ce que NaN ? "NaN", comme beaucoup d'entre vous l'ont deviné, est utilisé pour représenter "Pas un nombre" en Java. Il s'agit d'une valeur à virgule flottante spéciale pour indiquer les débordements et les erreurs. Il est généré lorsqu'un nombre à virgule flottante est divisé par zéro ou si la racine carrée d'un nombre négatif est calculée. NaN en Java - 1Par exemple, regardez l'extrait suivant.

public class NaN
{
    public static void main(String[]args)
    {
        System.out.println(0.0 / 0.0);	  //zero divided by zero
        System.out.println(Math.sqrt(-1)); //take sqrt of negative number
        System.out.println(10.0 % 0);      //taking mod by zero	
    }
}
Sortir

NaN                                                                                                                                           
NaN                                                                                                                                           
NaN
Dans l'extrait ci-dessus, vous pouvez observer que NaN est produit à la suite de 3 opérations simples :
  • Diviser un float / doublezéro par zéro.
  • Prendre la sous-racine d'un nombre négatif (Math.sqrt(-x)). En mathématiques, prendre la racine carrée d'un nombre négatif donne un nombre imaginaire . Ce cas est traité en retournant NaN en Java.
  • Prendre mod d'un nombre avec zéro, renverra le reste après avoir divisé une valeur par zéro. Par conséquent, NaN est renvoyé.

En quoi NaN est-il différent de l'infini positif et négatif?

Selon la spécification IEEE 754, il existe trois valeurs spéciales à virgule flottante et double pour gérer les cas limites :
  • Infini positif
  • Infini négatif
  • NaN
Le résultat de la division d'un nombre positif par 0 est l'infini positif. De même, l'infini négatif donne le résultat de la division d'un nombre négatif par zéro. Veuillez noter que toutes les valeurs à virgule flottante s'appliquent également au type de données double. La précision limitée des flotteurs n'est parfois pas suffisante. Cependant, nous verrons comment NaN fonctionne à la fois pour float et double dans une section ultérieure.

Qu'est-ce que la méthode NaN() ?

isNaN()est l'une des méthodes de base en Java pour vérifier s'il s'agit d'une valeur NaN ou non. Comme nous avons discuté des trois cas ci-dessus, il est temps de tester comment la méthode isNaN() différencie les valeurs +infinity , -infinity et NaN.

public class isNaN
{ public static void main(String[]args)
  { 
    Double posInfinity = +2.0 / 0.0;
    Double negInfinity = -3.5 / 0.0;
    Double nanVal = 50 % 0.0;


    System.out.println ("+" + posInfinity + ".IsNaN() = " + posInfinity.isNaN());
    System.out.println ( negInfinity + ".IsNaN() = " + negInfinity.isNaN());
    System.out.println ( nanVal +  ".IsNaN() = " + nanVal.isNaN());
  }
}
Sortir

+Infinity.IsNaN() = false                                                                                                                       
-Infinity.IsNaN() = false                                                                                                                       
NaN.IsNaN() = true

Comment comparer les valeurs NaN?

Chaque valeur NaN est considérée comme distincte. Cela signifie qu'aucun NaN n'est égal à un autre NaN. Selon ce principe, si vous comparez une valeur à une autre, le résultat est toujours négatif. Puisque NaN n'est pas ordonné, une comparaison numérique impliquant même un seul NaN renvoie faux. Java fournit Float.NaN et Double.NaN pour les champs constants des deux classes afin d'effectuer des comparaisons. Nous pouvons les différencier en deux scénarios distincts :
  • Vrai : uniquement en cas d'inégalité (!=)
  • Faux : pour tous les opérandes de comparaison (==, <=, >=, <, >)
Voici un exemple de travail pour vous les gars:

public class ComparingNaN
{ public static void main(String[] args)                                                                                                     
  {
    // Comparing NaN values for Float constants
    System.out.println (Float.NaN != Float.NaN); // true
    System.out.println (Float.NaN == Float.NaN); // false
    System.out.println (Float.NaN < Float.NaN);  // false
    System.out.println (Float.NaN > Float.NaN);  // false
    System.out.println (Float.NaN <= Float.NaN); // false
    System.out.println (Float.NaN >= Float.NaN); // false

    // Comparing NaN values for Float constants
    System.out.println (Double.NaN != Double.NaN); // true
    System.out.println (Double.NaN == Double.NaN); // false
    System.out.println (Double.NaN < Double.NaN);  // false
    System.out.println (Double.NaN > Double.NaN);  // false
    System.out.println (Double.NaN <= Double.NaN); // false
    System.out.println (Double.NaN >= Double.NaN); // false
  }
}

Comment générer des valeurs NaN ?

Avant de conclure, examinons quelques exemples courants d'obtention d'un Not a Number (nan).

public class GenerateNaNValues {  
  static final float ZERO = 0;
  public static void main (String[]args)
  {
    System.out.println("ZERO / ZERO = " + (ZERO / ZERO));
    System.out.println("+INFINITY - INFINITY = " + 
    (Float.POSITIVE_INFINITY + Float.NEGATIVE_INFINITY));
    System.out.println("-INFINITY * ZERO = " + (Float.NEGATIVE_INFINITY * ZERO));
    System.out.println("+INFINITY * ZERO = " + (Float.POSITIVE_INFINITY * ZERO));
    System.out.println("log10(-10) = " +  Math.log(-10));
    System.out.println("√-10 = " + Math.sqrt(-10));
    System.out.println("NaN + 10 = " + (Float.NaN + 10));
    System.out.println("NaN - 10 = " + (Float.NaN - 10));
    System.out.println("NaN * 10 = " + (Float.NaN * 10));
    System.out.println("NaN / 10 = " + (Float.NaN / 10));
    System.out.println("NaN + NaN = " + (Float.NaN + Float.NaN));
    System.out.println("NaN - NaN = " + (Float.NaN - Float.NaN));
    System.out.println("NaN * NaN = " + (Float.NaN * Float.NaN));
    System.out.println("NaN / NaN = " + (Float.NaN / Float.NaN));
  }
}
Sortir:

ZERO / ZERO = NaN                                                                                                                               
+INFINITY - INFINITY = NaN                                                                                                                      
-INFINITY * ZERO = NaN                                                                                                                          
+INFINITY * ZERO = NaN                                                                                                                          
log10(-10) = NaN                                                                                                                                
√-10 = NaN                                                                                                                                      
NaN + 10 = NaN                                                                                                                                    
NaN - 10 = NaN                                                                                                                                  
NaN * 10 = NaN                                                                                                                                  
NaN / 10 = NaN                                                                                                                                  
NaN + NaN = NaN                                                                                                                                 
NaN - NaN = NaN                                                                                                                                 
NaN * NaN = NaN                                                                                                                                 
NaN / NaN = NaN

Conclusion

Après avoir examiné les nombreuses opérations produisant du NaN, vous devez maintenant le connaître. Cela peut vous déconcerter au début, mais il n'y a rien de compliqué à gérer cela. En développant une petite habitude de vérifier si une valeur n'est pas NaN dans les calculs en virgule double/flottante, vous pouvez vous épargner beaucoup de tracas. Même si vous l'oubliez au début, c'est tout à fait correct. Vous pouvez toujours consulter cet article pour un dépannage mineur. La création de code compilable et sans erreur en une seule fois vient après des années d'expérience. Alors mettons-nous la main à la pâte dans le code et construisons quelque chose de génial !
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION