A Java nyelven a „NaN” a „Not a Number” rövidítése. Ez nem kivétel, hanem meglepő módon a NaN adattípusa is egy szám. De gyakran amikor a kezdő programozók véletlenül megkapják, tovább használják a számításaik során. Ezért a Java-ban nem kompatibilis adattípusok együttes használatuk esetén dobható hibát okozhatnak. Az is gyakran látható, hogy java.lang.ArithmeticException: / by zeroazonosnak tekintik a NaN-val. A Java azonban mindkettőt eltérően kezeli. Elég rejtélyes? Az átfogó megértés érdekében boncolgatjuk, miben különböznek ezek egymástól. A cikk végére megismerheti azokat a lehetséges műveleteket, amelyek nem számot (nan) hoznak létre, és néhány egyszerű kezelési módot.

Mi az a NaN?

Szóval, mi az a NaN? A „NaN”, ahogyan azt sokan sejtitek, a „Not a Number” kifejezést jelenti a Java nyelven. Ez egy speciális lebegőpontos érték a túlcsordulások és hibák jelzésére. Akkor jön létre, amikor egy lebegőpontos számot elosztunk nullával, vagy ha egy negatív szám négyzetgyökét számítjuk ki. NaN Java nyelven - 1Például nézze meg a következő részletet.

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	
    }
}
Kimenet

NaN                                                                                                                                           
NaN                                                                                                                                           
NaN
A fenti részletben megfigyelhető, hogy a NaN 3 egyszerű művelet eredményeként keletkezik:
  • Nulla elosztása float / doublenullával.
  • Negatív szám gyökér alatti felvétele (Math.sqrt(-x)). A matematikában egy negatív szám négyzetgyökének felvétele egy képzeletbeli számot eredményez . Ezt az esetet a NaN visszaadásával kezelik Java nyelven.
  • Ha egy számot nullával veszünk, akkor az érték nullával való elosztása után a maradékot adja vissza. Ezért a NaN visszaadásra kerül.

Miben különbözik a NaN a pozitív és a negatív végtelentől?

Az IEEE 754 specifikáció szerint három speciális lebegőpontos és dupla érték létezik a határesetek kezelésére:
  • Pozitív végtelen
  • Negatív végtelen
  • NaN
Egy pozitív szám 0-val való osztásának eredménye pozitív végtelen. Hasonlóképpen a negatív végtelenség eredménye, ha egy negatív számot elosztunk nullával. Vegye figyelembe, hogy minden lebegőpontos érték a double adattípusra is vonatkozik. Az úszók korlátozott pontossága időnként nem elegendő. Azonban egy későbbi részben meglátjuk, hogyan működik a NaN mind a float, mind a double esetében.

Mi az a NaN() módszer?

isNaN()a Java egyik alapvető módszere annak ellenőrzésére, hogy NaN-értékről van-e szó vagy sem. Ahogy fentebb három esetet tárgyaltunk, ideje tesztelni, hogy az isNaN() metódus hogyan tesz különbséget a +infinity , -infinity és a NaN értékek között.

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());
  }
}
Kimenet

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

Hogyan hasonlítsuk össze a NaN értékeket?

Minden NaN értéket különállónak tekintünk. Ez azt jelenti, hogy egyetlen NaN sem egyenlő más NaN-lel. Ezen elv szerint, ha egy értéket a másikhoz hasonlítunk, az eredmény mindig negatív. Mivel a NaN rendezetlen, így a numerikus összehasonlítás akár egyetlen NaN-t is hamis eredményt ad. A Java mindkét osztályban biztosítja a Float.NaN és a Double.NaN konstans mezőit az összehasonlítások elvégzéséhez. Ezeket két külön forgatókönyv szerint különböztethetjük meg:
  • Igaz: Csak egyenlőtlenség esetén (!=)
  • Hamis: Minden összehasonlító operandushoz (==, <=, >=, <, >)
Íme egy működő példa nektek:

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
  }
}

Hogyan lehet NaN értékeket generálni?

Mielőtt befejezné, nézzünk meg néhány gyakori példát a Nem szám (nan) megszerzésére.

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));
  }
}
Kimenet:

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

Következtetés

Miután megvizsgálta a NaN-t előállító számos műveletet, most már ismernie kell. Kezdetben talán zavarba ejt, de nincs semmi bonyolult ennek a kezelésében. Ha kialakítunk egy kis szokást annak ellenőrzésére, hogy egy érték nem NaN-e a duplapontos/lebegőpontos számításoknál, sok gondtól megkímélheti magát. Még ha először elfelejti is, akkor is teljesen rendben van. Bármikor elolvashatja ezt a cikket a kisebb hibaelhárításhoz. A lefordítható, hibamentes kód egy menetben történő létrehozása több éves tapasztalat eredménye. Tehát piszkáljuk be a kezünket a kóddal, és építsünk valami nagyszerűt!