NaN i Java

1. Oversigt

Kort fortalt, NaN er en numerisk datatypeværdi, der står for “ikke et tal”.

I denne hurtige vejledning forklarer vi NaN værdi i Java og de forskellige operationer, der kan producere eller involvere denne værdi.

2. Hvad er? NaN?

NaN angiver normalt resultatet af ugyldige handlinger. For eksempel er forsøg på at dividere nul med nul en sådan handling.

Vi bruger også NaN for ikke-repræsentative værdier. Kvadratroden på -1 er et sådant tilfælde, da vi kan beskrive værdien (jeg) kun i komplekse tal.

IEEE-standarden for flydende aritmetik (IEEE 754) definerer NaN værdi. I Java er typerne med flydende punkt flyde og dobbelt implementere denne standard.

Java definerer NaN konstanter af begge flyde og dobbelt typer som Flyde.NaN og Dobbelt.NaN:

En konstant, der holder en Not-a-Number (NaN) værdi af typen dobbelt. Det svarer til den værdi, der returneres af Double.longBitsToDouble (0x7ff8000000000000L). ”

og:

“En konstant holder en Not-a-Number (NaN) værdi af typen float. Det svarer til den værdi, der returneres af Float.intBitsToFloat (0x7fc00000). ”

Vi har ikke denne type konstanter til andre numeriske datatyper i Java.

3. Sammenligninger med NaN

Mens vi skriver metoder i Java, skal vi kontrollere, at input er gyldigt og inden for det forventede interval. NaN værdi er i de fleste tilfælde ikke et gyldigt input. Derfor skal vi kontrollere, at inputværdien ikke er a NaN værdi og håndter disse inputværdier korrekt.

NaN kan ikke sammenlignes med nogen flydende type værdi. Det betyder, at vi får falsk til alle sammenligningsoperationer, der involverer NaN (undtagen “! =”, som vi får rigtigt).

Vi får rigtigt til "x! = x ” hvis og kun hvis x er NaN:

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

Lad os se på resultatet af at køre koden ovenfor:

NaN == 1 = falsk NaN> 1 = falsk NaN NaN = falsk NaN <NaN = falsk NaN! = NaN = sand 

Derfor, vi kan ikke kontrollere NaN ved at sammenligne med NaN ved hjælp af “==” eller “! =“. Faktisk bør vi sjældent bruge "==" eller "! =" Operatører med flyde eller dobbelt typer.

I stedet kan vi bruge udtrykket “x != x ”. Dette udtryk returnerer kun sandt for NAN.

Vi kan også bruge metoderne Float.isNaN og Double.isNaN for at kontrollere disse værdier. Dette er den foretrukne tilgang, da den er mere læselig og forståelig:

dobbelt x = 1; System.out.println (x + "er NaN =" + (x! = X)); System.out.println (x + "er NaN =" + (Double.isNaN (x))); x = Double.NaN; System.out.println (x + "er NaN =" + (x! = X)); System.out.println (x + "er NaN =" + (Double.isNaN (x))); 

Vi får følgende resultat, når du kører denne kode:

1.0 er NaN = falsk 1.0 er NaN = falsk NaN er NaN = sand NaN er NaN = sand

4. Produktion af operationer NaN

Mens du udfører operationer, der involverer flyde og dobbelt typer, skal vi være opmærksomme på NaN værdier.

Nogle floating point-metoder og operationer producerer NaN værdier i stedet for at kaste et Undtagelse. Vi skal muligvis håndtere sådanne resultater eksplicit.

En almindelig sag, der resulterer i ikke-et-tal-værdier er matematiske udefinerede numeriske operationer:

dobbelt NUL = 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)); 

Disse eksempler resulterer i følgende output:

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

Numeriske operationer, der ikke har resultater i reelle tal, producerer også NaN:

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

Disse udsagn vil resultere i:

Kvadratrod på -1 = NaN LOG PÅ -1 = NaN 

Alle numeriske operationer med NaN som en operand-produktion NaN som resultat:

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)); 

Og resultatet af ovenstående er:

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

Endelig kan vi ikke tildele nul til dobbelt eller flyde type variabler. I stedet kan vi eksplicit tildele NaN til sådanne variabler for at angive manglende eller ukendte værdier:

dobbelt maxValue = Double.NaN;

5. Konklusion

I denne artikel diskuterede vi NaN og de forskellige operationer, der involverer det. Vi diskuterede også behovet for at håndtere NaN mens du eksplicit udfører beregninger med flydende punkt i Java.

Den fulde kildekode kan findes på GitHub.