NaN

Inom beräkningar är NaN ( / n värde n / ), æ som står för Not a Number , en medlem av en numerisk datatyp som kan tolkas som ett som är odefinierat eller orepresenterbart, särskilt i aritmetik med flyttal . Systematisk användning av NaNs introducerades av IEEE 754 flyttalsstandarden 1985, tillsammans med representationen av andra icke-ändliga kvantiteter som oändligheter .

I matematik är noll delat med noll odefinierat och representeras därför av NaN i datorsystem . Kvadratroten ur ett negativt tal är inte ett reellt tal, och representeras därför också av NaN i kompatibla datorsystem . NaNs kan också användas för att representera saknade värden i beräkningar.

Två separata typer av NaNs tillhandahålls, benämnda tysta NaNs och signalerande NaNs . Tysta NaNs används för att sprida fel som härrör från ogiltiga operationer eller värden. Signalerande NaN kan stödja avancerade funktioner som att blanda numerisk och symbolisk beräkning eller andra tillägg till grundläggande flyttalsaritmetik.

Flytpunkt

I flyttalsberäkningar är NaN inte detsamma som oändlighet , även om båda vanligtvis hanteras som specialfall i flyttalsrepresentationer av reella tal såväl som i flyttalsoperationer. En ogiltig operation är inte heller detsamma som ett aritmetiskt överflöde (som skulle returnera en oändlighet eller det största ändliga talet i magnitud) eller ett aritmetiskt underflöde (som skulle returnera det minsta normaltalet i storlek, ett subnormalt tal eller noll ).

IEEE 754 NaNs kodas med exponentfältet fyllt med ettor (som oändlighetsvärden), och något icke-nolltal i signifikandfältet (för att göra dem åtskilda från oändlighetsvärden); detta tillåter definitionen av flera distinkta NaN-värden, beroende på vilka bitar som är satta i signifikandfältet, men också på värdet på den ledande teckenbiten (men applikationer krävs inte för att tillhandahålla distinkt semantik för dessa distinkta NaN-värden).

Till exempel skulle en IEEE 754 enkelprecision (32-bitars) NaN kodas som

s 111 1111 1 xxx xxxx xxxx xxxx xxxx xxxx

där s är tecknet (oftast ignoreras i applikationer) och x- sekvensen representerar ett tal som inte är noll (värdet noll kodar oändligheter). I praktiken används den mest signifikanta biten från x för att bestämma typen av NaN: " tyst NaN " eller " signalerande NaN " (se detaljer i Kodning ). De återstående bitarna kodar en nyttolast (som oftast ignoreras i applikationer).

Flyttalsoperationer andra än ordnade jämförelser sprider normalt ett tyst NaN ( qNaN ). De flesta flyttalsoperationer på en signalerande NaN ( sNaN ) signalerar det ogiltiga operationsundantaget; standardundantagsåtgärden är då densamma som för qNaN-operander och de producerar ett qNaN om de producerar ett flyttalsresultat.

00 Utbredningen av tysta NaN genom aritmetiska operationer gör att fel kan upptäckas i slutet av en sekvens av operationer utan omfattande testning under mellanliggande stadier. Till exempel, om man börjar med en NaN och lägger till 1 fem gånger i rad, resulterar varje tillägg i en NaN, men det finns ingen anledning att kontrollera varje beräkning eftersom man bara kan notera att slutresultatet är NaN. Men beroende på språk och funktion kan NaNs tyst tas bort från en kedja av beräkningar där en beräkning i kedjan skulle ge ett konstant resultat för alla andra flyttalsvärden. Till exempel kan beräkningen x ge resultatet 1, även när x är NaN, så att kontrollera endast det slutliga resultatet skulle dölja det faktum att en beräkning före x resulterade i ett NaN. I allmänhet behövs alltså ett senare test för en uppsättning ogiltig flagga för att upptäcka alla fall där NaNs introduceras (se Funktionsdefinition nedan för ytterligare detaljer).

I avsnitt 6.2 i den gamla IEEE 754-2008 -standarden finns det två avvikande funktioner ( funktionerna maxNum och minNum , som returnerar det maximala respektive minimum av två operander som förväntas vara tal) som gynnar siffror - om bara en av operanderna är en NaN, då returneras värdet på den andra operanden. Revisionen av IEEE 754-2019 har ersatt dessa funktioner eftersom de inte är associativa (när en signalerande NaN visas i en operand).

Jämförelse med NaN

Jämförelser specificeras av IEEE 754- standarden för att ta hänsyn till möjliga NaN-operander. När man jämför två reella tal, eller utökade reella tal (som i IEEE 754 flyttalsformat), kan det första talet vara antingen mindre än, lika med eller större än det andra talet. Detta ger tre möjliga samband. Men när minst en operand av en jämförelse är NaN, gäller inte denna trikotomi, och en fjärde relation behövs: oordnad . I synnerhet två NaN-värden jämförs som oordnade, inte lika.

Som specificerat returnerar predikaten som är associerade med <, ≤, =, ≥, > matematiska symboler (eller motsvarande notation i programmeringsspråk) falskt på en oordnad relation. Så, till exempel, NOT ( x < y ) är inte logiskt ekvivalent med x y : på oordning, dvs när x eller y är NaN, returnerar den förra sant medan den senare returnerar falskt. Emellertid definieras ≠ som negationen av =, så den returnerar sant på oordning.


Jämförelse mellan NaN och eventuellt flyttalsvärde x (inklusive NaN och ±∞)
Jämförelse NaN ≥ x NaN ≤ x NaN > x NaN < x NaN = x NaN ≠ x
Resultat Falsk Falsk Falsk Falsk Falsk Sann

Från dessa regler kan x x eller x = x användas för att testa om x är NaN eller icke-NaN.

Jämförelsepredikaten är antingen signalering eller icke-signalering på tysta NaN-operander; signaleringsversionerna signalerar undantaget med ogiltig operation för sådana jämförelser (dvs. som standard ställer detta bara in motsvarande statusflagga utöver beteendet hos de icke-signalerande versionerna). Predikaten för jämlikhet och ojämlikhet är icke-signalerande. De andra standardjämförelsepredikaten associerade med ovanstående matematiska symboler signalerar alla om de tar emot en NaN-operand. Standarden tillhandahåller även icke-signalerande versioner av dessa andra predikat. Predikatet isNaN( x ) bestämmer om ett värde är ett NaN och signalerar aldrig ett undantag, även om x är ett signalerande NaN.

IEEE flyttalsstandard kräver att NaN ≠ NaN håller. Däremot har 2022 års privata standard för positaritmetik ett liknande koncept, NaR (Not a Real), där NaR = NaR gäller.

Operationer som genererar NaN

Det finns tre typer av operationer som kan returnera NaN:

  • De flesta operationer med minst en NaN-operand.
  • Obestämda former :
    • Divisionerna (±0) / (±0) och (±∞) / (±∞) .
    • Multiplikationerna (±0) × (±∞) och (±∞) × (±0) .
    • Resten x % y när x är en oändlighet eller y är noll.
    • Adderingarna (+∞) + (−∞) , (−∞) + (+∞) och ekvivalenta subtraktioner (+∞) − (+∞) och (−∞) − (−∞) .
    • Standarden har alternativa funktioner för krafter:
      • 00 Standard- pow - funktionen och heltalsexponent- pown -funktionen definierar 1 och 0 som 1 .
      • Powr - funktionen definierar alla tre obestämda formerna som ogiltiga operationer och returnerar därför NaN.
  • Verkliga operationer med komplexa resultat, till exempel:
    • Kvadratroten ur ett negativt tal.
    • Logaritmen för ett negativt tal .
    • Invers sinus eller invers cosinus för ett tal som är mindre än −1 eller större än 1.

NaNs kan också explicit tilldelas variabler, vanligtvis som en representation för saknade värden. Före IEEE-standarden använde programmerare ofta ett speciellt värde (som −99999999) för att representera odefinierade eller saknade värden, men det fanns ingen garanti för att de skulle hanteras konsekvent eller korrekt.

NaN genereras inte nödvändigtvis i alla ovanstående fall. Om en operation kan ge ett undantagstillstånd och traps inte maskeras kommer operationen att orsaka en trap istället. Om en operand är en tyst NaN, och det inte heller finns någon signalerande NaN-operand, så finns det inget undantagstillstånd och resultatet är en tyst NaN. Explicita tilldelningar kommer inte att orsaka ett undantag även för signalering av NaN.

Tyst NaN

Tysta NaNs, eller qNaNs, ger inga ytterligare undantag eftersom de sprider sig genom de flesta operationer. Undantagen är där NaN inte helt enkelt kan överföras oförändrat till utgången, till exempel i formatkonverteringar eller vissa jämförelseoperationer.

Signalerar NaN

Signalerande NaNs, eller sNaNs, är speciella former av ett NaN som, när det konsumeras av de flesta operationer, bör höja undantaget för ogiltiga operationer och sedan, om så är lämpligt, "tystas" till ett qNaN som sedan kan spridas. De introducerades i IEEE 754 . Det har funnits flera idéer för hur dessa kan användas:

  • Att fylla oinitierat minne med signalerande NaN skulle producera det ogiltiga operationsundantaget om data används innan den initieras
  • Använda en sNaN som platshållare för ett mer komplicerat objekt , till exempel:

När den påträffas kan en fällhanterare avkoda sNaN och returnera ett index till det beräknade resultatet. I praktiken står detta tillvägagångssätt inför många komplikationer. Behandlingen av teckenbiten för NaNs för vissa enkla operationer (som absolut värde ) skiljer sig från den för aritmetiska operationer. Fällor krävs inte av standarden. Det finns andra tillvägagångssätt för denna typ av problem som skulle vara mer bärbara. [ citat behövs ]

Nyttolastoperationer

IEEE 754-2019 rekommenderar att operationerna getPayload , setPayload och setPayloadSignaling implementeras, vilket standardiserar åtkomsten till nyttolaster för att effektivisera applikationsanvändningen. Enligt IEEE 754-2019-bakgrundsdokumentet ska denna rekommendation tolkas som "krävs för nya implementeringar, med reservation för bakåtkompatibilitet".

Kodning

I IEEE 754 standardöverensstämmande flyttalslagringsformat identifieras NaNs av specifika, fördefinierade bitmönster som är unika för NaNs. Teckenbiten spelar ingen roll. Binärt format NaNs representeras med det exponentiella fältet fyllt med ettor (som oändlighetsvärden) och ett tal som inte är noll i signifikansfältet (för att göra dem åtskilda från oändlighetsvärden). Den ursprungliga IEEE 754-standarden från 1985 ( IEEE 754-1985 ) beskrev bara binära flyttalsformat och specificerade inte hur signalering/tyst tillstånd skulle märkas. I praktiken avgjorde den mest signifikanta biten av signifikandfältet om en NaN är signalerande eller tyst. Två olika implementeringar, med omvänd betydelse, resulterade:

  • de flesta processorer (inklusive de från Intel och AMD :s x86 -familjen, Motorola 68000-familjen , AIM PowerPC -familjen, ARM -familjen, Sun SPARC -familjen och eventuellt nya MIPS -processorer) ställer in signalerings-/tystbiten till icke-noll om NaN är tyst och till noll om NaN signalerar. Således, på dessa processorer, representerar biten en is_quiet -flagga;
  • i NaN genererade av PA-RISC och gamla MIPS-processorer är signalerings-/tystbiten noll om NaN är tyst och icke-noll om NaN signalerar. På dessa processorer representerar således biten en is_signaling- flagga.

Det förra valet har föredragits eftersom det tillåter implementeringen att tysta en signalerande NaN genom att bara ställa in signalerings/tyst bit till 1. Det omvända är inte möjligt med det senare valet eftersom inställning av signalering/tyst bit till 0 kan ge en oändlighet.

2008 och 2019 års revisioner av IEEE 754-standarden innehåller formella krav och rekommendationer för kodning av signalering/tyst tillstånd.

  • För binära utbytesformat används den mest signifikanta biten av signifikandfältet uteslutande för att skilja mellan tysta och signalerande NaNs. Dessutom bör det vara en is_quiet flagga. Det vill säga, denna bit är icke-noll om NaN är tyst och noll om NaN signalerar.
  • För decimalutbytesformat, oavsett om det är binärt eller decimalkodat, identifieras en NaN genom att de fem översta bitarna i kombinationsfältet efter teckenbiten är inställda på ettor. Den sjätte biten i fältet är is_signaling- flaggan. Det vill säga, denna bit är noll om NaN är tyst och icke-noll om NaN signalerar.

För IEEE 754-2008-överensstämmelse är innebörden av signalerings-/tystbiten i de senaste MIPS-processorerna nu konfigurerbar via NAN2008-fältet i FCSR-registret. Detta stöd är valfritt i MIPS Release 3 och krävs i Release 5.

Tillståndet/värdet för de återstående bitarna i signifikansfältet definieras inte av standarden. Detta värde kallas "nyttolasten" för NaN. Om en operation har en enda NaN-ingång och sprider den till utgången, bör resultatet NaN:s nyttolast vara den för ingången NaN (detta är inte alltid möjligt för binära format när signalering/tyst tillstånd är kodat av en is_signaling-flagga, som förklarats ovan). Om det finns flera NaN-ingångar, bör resultatet av NaN:s nyttolast vara från en av de ingående NaN:erna; standarden anger inte vilken.

Funktionsdefinition

Det finns olika åsikter om den korrekta definitionen av resultatet av en numerisk funktion som får en tyst NaN som indata. En uppfattning är att NaN bör spridas till utgången av funktionen i alla fall för att sprida indikationen på ett fel. En annan uppfattning, och den som tas av ISO C99 och IEEE 754-2008 i allmänhet, är att om funktionen har flera argument och utdata bestäms unikt av alla icke-NaN-ingångar (inklusive oändlighet), så bör det värdet bli resultatet. Så till exempel är värdet som returneras av hypot(±∞, qNaN) och hypot(qNaN, ±∞) +∞.

00 Problemet är särskilt akut för ( x exponentieringsfunktionen y ) = x y . pow , Uttrycken 0 , ∞ och 1 anses vara obestämda former när de förekommer som gränser (precis som ∞ × 0), och frågan om noll till nollpotensen ska definieras som 1 har delat uppfattning.

Om utgången betraktas som odefinierad när en parameter är odefinierad, bör pow(1, qNaN) producera ett qNaN. Matematikbibliotek har dock vanligtvis returnerat 1 för pow(1, y ) för alla reella tal y , och även när y är en oändlighet . På samma sätt producerar de 1 för pow( x , 0) även när x är 0 eller en oändlighet. Skälet till att returnera värdet 1 för de obestämda formerna var att värdet av funktioner i singulära punkter kan tas som ett visst värde om det värdet är inom gränsen för värdet [ förtydligande behövs ] för alla utom en försvinnande liten del av en boll runt gränsvärdet för parametrarna. [ citat behövs ] 2008 års version av IEEE 754- standarden säger att pow(1, qNaN) och pow(qNaN, 0) båda ska returnera 1 eftersom de returnerar 1 vad som helst som används istället för tyst NaN. Dessutom valde ISO C99, och senare IEEE 754-2008, att specificera pow(−1, ±∞) = 1 istället för qNaN; anledningen till detta val ges i C-rationalen: "Generellt undviker C99 ett NaN-resultat där ett numeriskt värde är användbart. ... Resultatet av pow(−2, ∞) är +∞, eftersom alla stora positiva flytande- poängvärden är jämna heltal."

För att tillfredsställa de som önskar en mer strikt tolkning av hur potensfunktionen ska agera, definierar 2008 års standard ytterligare två potensfunktioner: pown( x , n ) , där exponenten måste vara ett heltal, och powr( x , y ) , som returnerar a NaN närhelst en parameter är en NaN eller exponentieringen skulle ge en obestämd form .

Heltal NaN

heltalsformat med fast storlek kan inte uttryckligen indikera ogiltiga data. I ett sådant fall, när NaN konverteras till en heltalstyp, kräver IEEE 754- standarden att ett ogiltigt operationsundantag signaleras. Till exempel i Java ger sådana operationer instanser av java.lang.ArithmeticException . I C leder de till odefinierat beteende , men om bilaga F stöds, ger operationen ett "ogiltigt" flyttalsundantag (som krävs av IEEE-standarden) och ett ospecificerat värde.

Perls Math ::BigInt -paket använder "NaN" för resultatet av strängar som inte representerar giltiga heltal.


 > perl -mMath::BigInt -e "print Math::BigInt->new('foo')"  NaN 

Visa

Olika operativsystem och programmeringsspråk kan ha olika strängrepresentationer av NaN.

 nan (C, C++, Python) NaN (ECMAScript, Rust, C#, Julia).  Julia kan visa alternativa NaN, beroende på precision, NaN32 och NaN16; NaN är för Float64 typ.   NaN% NAN (C, C++, Rust) NaNQ (IBM XL och AIX: Fortran, C++ förslag n2290) NaNS (ditto) qNaN sNaN 1.#SNAN (Excel) 1.#QNAN (Excel) -1.#IND (Excel) ) +nan.0 (schema) 

Eftersom kodade NaNs i praktiken har ett tecken, en tyst/signaleringsbit och valfri "diagnostisk information" (kallas ibland en nyttolast ), kommer dessa ibland också att finnas i strängrepresentationer av NaNs. Några exempel är:

  • För C- och C++-språken visas teckenbiten alltid av standardbiblioteksfunktionerna (t.ex. -nan ) när de finns. Det finns ingen standardvisning av nyttolasten eller signaleringsstatusen, men ett tyst NaN-värde för en specifik nyttolast kan antingen konstrueras genom att tillhandahålla strängen nan( char -sequence ) till en nummeranalysfunktion (t.ex. strtod ) eller genom att tillhandahålla char - sekvenssträngen till nan() (eller nans() för sNaN), båda tolkade på ett implementeringsdefinierat sätt.
    • GCC och LLVM tillhandahåller inbyggda implementeringar av nan() och nans() . De analyserar char-sekvensen som ett heltal för strtoull (eller en motsvarighet av annan storlek) med dess detektering av heltalsbaser.
    • GNU C-bibliotekets float-parser använder char-sequence- strängen på "något ospecificerat sätt". I praktiken har denna analys varit likvärdig med GCC/LLVM för upp till 64 bitars nyttolast.
    • Newlib implementerar inte nan() -analys, men strtod() accepterar ett hexadecimalt format utan prefix.
    • musl implementerar inte någon nyttolastanalys.

Inte alla språk medger att det finns flera NaN. Till exempel använder ECMAScript bara ett NaN-värde genomgående.

Anteckningar

Citat

Standarder

externa länkar