John Squirrels
Nivå
San Francisco

NaN i Java

Publicerad i gruppen
I Java står "NaN" för "Not a Number". Det är inte en typ av undantag, snarare överraskande, datatypen för NaN är också ett nummer. Men ofta när nybörjare programmerare får det oavsiktligt, använder de det vidare i sina beräkningar. Därför kan inkompatibla datatyper i Java när de används tillsammans orsaka ett kastbart fel. Det ses också ofta som java.lang.ArithmeticException: / by zeroanses vara detsamma som NaN. Men Java behandlar dem båda olika. Förbryllande nog? För din övergripande förståelse kommer vi att dissekera hur dessa skiljer sig från varandra. I slutet av den här artikeln kommer du att lära dig om möjliga operationer som inte producerar ett nummer (nan), och några enkla sätt att hantera det.

Vad är NaN?

Så, vad är NaN? "NaN" som många av er har gissat används för att representera "Not a Number" i Java. Det är ett speciellt flyttalsvärde för att beteckna spill och fel. Det genereras när ett flyttal delas med noll eller om kvadratroten av ett negativt tal beräknas. NaN i Java - 1Titta till exempel på följande utdrag.

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

NaN                                                                                                                                           
NaN                                                                                                                                           
NaN
I utdraget ovan kan du observera att NaN produceras som ett resultat av 3 enkla operationer:
  • Att dividera en float / doublenolla med noll.
  • Ta under roten av ett negativt tal (Math.sqrt(-x)). I matematik ger kvadratroten av ett negativt tal ett imaginärt tal . Detta fall hanteras genom att returnera NaN i Java.
  • Om du tar mod av ett tal med noll, returneras resten efter att ha dividerat ett värde med noll. Därför returneras NaN.

Hur skiljer sig NaN från positiv och negativ oändlighet?

Enligt IEEE 754-specifikationen finns det tre speciella flyttals- och dubbla värden för att hantera gränsfallen:
  • Positiv oändlighet
  • Negativ oändlighet
  • NaN
Resultatet av att dividera ett positivt tal med 0 är positiv oändlighet. På liknande sätt ger negativ oändlighet som ett resultat av att dividera ett negativt tal med noll. Observera att alla flyttalsvärden är tillämpliga på datatyp dubbel också. Den begränsade precisionen hos flottörer är ibland inte tillräcklig. Vi får dock se hur NaN fungerar för både float och double i ett senare avsnitt.

Vad är NaN()-metoden?

isNaN()är en av de grundläggande metoderna i Java för att kontrollera om det är ett NaN-värde eller inte. Eftersom vi diskuterade tre fall ovan, är det dags att testa hur isNaN()-metoden skiljer mellan +oändlighet , -oändlighet och NaN-värden.

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

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

Hur jämför man NaN-värden?

Varje NaN-värde anses vara distinkt. Det betyder att inte en enda NaN är lika med någon annan NaN. Enligt denna princip är resultatet alltid negativt om du jämför ett värde med ett annat. Eftersom NaN är oordnad, så returnerar en numerisk jämförelse som involverar ens en enda NaN falskt. Java tillhandahåller Float.NaN och Double.NaN för konstanta fält i båda klasserna för att utföra jämförelser. Vi kan skilja dessa åt i två separata scenarier:
  • Sant: Endast vid ojämlikhet (!=)
  • Falskt: För alla jämförelseoperander (==, <=, >=, <, >)
Här är ett fungerande exempel för er:

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

Hur genererar man NaN-värden?

Innan vi avslutar, låt oss titta på några vanliga exempel på att få ett 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));
  }
}
Produktion:

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

Slutsats

Efter att ha tittat på de många operationerna som producerar NaN, måste du vara bekant med det nu. Det kan förbrylla dig till en början, men det är inget komplicerat att hantera detta. Genom att utveckla en liten vana att kontrollera om ett värde inte är NaN i dubbel-/flyttalsberäkningar kan du rädda dig från mycket krångel. Även om du glömmer detta från början är det helt okej. Du kan alltid konsultera den här artikeln för mindre felsökning. Att skapa kompilerbar, felfri kod på en gång kommer efter många års erfarenhet. Så låt oss smutsa ner händerna på kod och bygga något fantastiskt!
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION