John Squirrels
Nivel
San Francisco

NaN în Java

Publicat în grup
În Java, „NaN” înseamnă „Not a Number”. Nu este un tip de excepție, mai degrabă surprinzător, tipul de date al NaN este, de asemenea, un număr. Dar adesea, când programatorii începători îl obțin neintenționat, îl folosesc în continuare în calculele lor. Prin urmare, tipurile de date incompatibile în Java atunci când sunt utilizate împreună pot provoca o eroare care poate fi aruncată. De asemenea, se vede în mod obișnuit că java.lang.ArithmeticException: / by zeroeste considerat la fel cu NaN. Cu toate acestea, Java le tratează pe ambele în mod diferit. Destul de derutant? Pentru înțelegerea dvs. cuprinzătoare, vom analiza modul în care acestea sunt diferite unele de altele. Până la sfârșitul acestui articol, veți afla despre posibilele operațiuni care nu produc un număr (nan) și câteva modalități ușoare de a-l gestiona.

Ce este NaN?

Deci, ce este NaN? „NaN”, după cum mulți dintre voi ați ghicit, este folosit pentru a reprezenta „Nu este un număr” în Java. Este o valoare specială în virgulă mobilă pentru a indica depășiri și erori. Este generat atunci când un număr în virgulă mobilă este împărțit la zero sau dacă se calculează rădăcina pătrată a unui număr negativ. NaN în Java - 1De exemplu, aruncați o privire la următorul fragment.
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
    }
}
Ieșire
NaN
NaN
NaN
În fragmentul de mai sus, puteți observa că NaN este produs ca urmare a 3 operații simple:
  • Împărțirea unui float / doublezero cu zero.
  • Luarea sub rădăcină a unui număr negativ (Math.sqrt(-x)). În matematică, luarea rădăcinii pătrate a unui număr negativ are ca rezultat un număr imaginar . Acest caz este tratat prin returnarea NaN în Java.
  • Luând modificarea unui număr cu zero, va returna restul după împărțirea unei valori la zero. Prin urmare, NaN este returnat.

Cum este NaN diferit de infinitul pozitiv și negativ?

Conform specificației IEEE 754, există trei valori speciale în virgulă mobilă și duble pentru a gestiona cazurile limită:
  • Infinitul pozitiv
  • Infinitul negativ
  • NaN
Rezultatul împărțirii unui număr pozitiv la 0 este infinitul pozitiv. În mod similar, infinitul negativ rezultă ca rezultat al împărțirii unui număr negativ cu zero. Vă rugăm să rețineți că toate valorile în virgulă mobilă sunt aplicabile și tipului de date double. Precizia limitată a flotoarelor nu este uneori suficientă. Cu toate acestea, vom vedea cum funcționează NaN atât pentru float, cât și pentru dublu într-o secțiune ulterioară.

Ce este metoda NaN()?

isNaN()este una dintre metodele de bază din Java pentru a verifica dacă este o valoare NaN sau nu. După cum am discutat trei cazuri mai sus, este timpul să testăm modul în care metoda isNaN() diferențiază între valorile +infinity , -infinity și 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());
  }
}
Ieșire
+Infinity.IsNaN() = false
-Infinity.IsNaN() = false
NaN.IsNaN() = true

Cum se compară valorile NaN?

Fiecare valoare NaN este considerată distinctă. Aceasta înseamnă că niciun NaN nu este egal cu niciun alt NaN. Prin acest principiu, dacă comparați o valoare cu alta, rezultatul este întotdeauna negativ. Deoarece NaN este neordonat, deci o comparație numerică care implică chiar și un singur NaN returnează fals. Java oferă Float.NaN și Double.NaN pentru câmpurile constante din ambele clase pentru a efectua comparații. Le putem diferenția în două scenarii separate:
  • Adevărat: numai în caz de inegalitate (!=)
  • Fals: pentru toți operanzii de comparație (==, <=, >=, <, >)
Iată un exemplu de lucru pentru voi băieți:
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
  }
}

Cum se generează valori NaN?

Înainte de a încheia, să ne uităm la câteva exemple comune de obținere a unui 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));
  }
}
Ieșire:
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

Concluzie

După ce te uiți la numeroasele operațiuni care produc NaN, trebuie să fii familiarizat cu el acum. S-ar putea să te încurce inițial, dar nu este nimic complicat să faci asta. Dezvoltând un mic obicei de a verifica dacă o valoare nu este NaN în calculele cu virgulă dublă/în virgulă mobilă, vă poate scuti de o mulțime de bătăi de cap. Chiar dacă ai uitat asta inițial, este în regulă. Puteți consulta oricând acest articol pentru depanare minoră. Crearea unui cod compilabil, fără erori dintr-o singură mișcare, vine după ani de experiență. Deci haideți să ne murdărim mâinile în cod și să construim ceva grozav!
Comentarii
  • Popular
  • Nou
  • Vechi
Trebuie să fii conectat pentru a lăsa un comentariu
Această pagină nu are încă niciun comentariu