NaN - NaN

Ve výpočetní technice je NaN ( / n æ n / ), což znamená Not a Number , členem numerického datového typu, který lze interpretovat jako hodnotu, která je nedefinovaná nebo nereprezentovatelná, zejména v aritmetice s pohyblivou řádovou čárkou . Systematické používání NaN bylo zavedeno standardem IEEE 754 s plovoucí desetinnou čárkou v roce 1985 spolu se zastoupením dalších nekončitých veličin, jako jsou nekonečna .

V matematice je nula dělená nulou nedefinována jako reálné číslo , a proto je ve výpočetních systémech reprezentována NaN. Odmocnina z řady negativní , není reálné číslo, a proto je také reprezentována NaN ve vyhovujících výpočetních systémů. NaN mohou být také použity k reprezentaci chybějících hodnot ve výpočtech.

K dispozici jsou dva samostatné druhy NaN, nazývané tiché NaN a signalizační NaN . K šíření chyb vyplývajících z neplatných operací nebo hodnot se používají tiché NaN. Signalizační NaN mohou podporovat pokročilé funkce, jako je míchání numerických a symbolických výpočtů nebo jiná rozšíření základní aritmetiky s pohyblivou řádovou čárkou.

Plovoucí bod

Při výpočtech s plovoucí desetinnou čárkou není NaN totéž jako nekonečno , ačkoli oba jsou obvykle zpracovávány jako speciální případy v reprezentacích reálných čísel s plovoucí desetinnou čárkou a také v operacích s plovoucí desetinnou čárkou. Neplatný provoz je také není stejný jako přetečení (který může vrátit nekonečno) nebo aritmetické podtečení (která vrátí nejmenší normální počet , je číslo denormal nebo nula ).

IEEE 754 NaN jsou kódovány exponentovým polem vyplněným jedničkami (jako jsou hodnoty nekonečna) a některým nenulovým číslem v poli významů (aby byly odlišné od hodnot nekonečna); to umožňuje definici více odlišných hodnot NaN v závislosti na tom, které bity jsou nastaveny v poli Význam, ale také na hodnotě úvodního znaménkového bitu (ale aplikace nejsou povinny poskytovat odlišnou sémantiku pro tyto odlišné hodnoty NaN).

Například bit Nawise IEEE 754 s jednoduchou přesností (32bitový) NaN by byl

s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx

kde s je znaménko (v aplikacích se nejčastěji ignoruje) a sekvence x představuje nenulové číslo (hodnota nula kóduje nekonečna). Nejvýznamnější bit z x se používá k určení typu NaN: „tichý NaN“ nebo „signalizující NaN“. Zbývající bity kódují užitečné zatížení (v aplikacích se nejčastěji ignoruje).

Operace s pohyblivou řádovou čárkou jiné než seřazené srovnání normálně šíří tichý NaN ( qNaN ). Většina operací s pohyblivou řádovou čárkou na signalizačním NaN ( sNaN ) signalizuje výjimku neplatné operace; výchozí akce výjimky je pak stejná jako pro operandy qNaN a produkují qNaN, pokud vytváří výsledek s plovoucí desetinnou čárkou.

Šíření tichých NaN pomocí aritmetických operací umožňuje detekci chyb na konci sekvence operací bez rozsáhlého testování v mezistupních. Pokud například jeden začíná NaN a přidá 1 pětkrát za sebou, každé přidání vede k NaN, ale není nutné kontrolovat každý výpočet, protože je možné poznamenat, že konečným výsledkem je NaN. V závislosti na jazyce a funkci však lze NaN bez potíží odstranit z řetězce výpočtů, kde by jeden výpočet v řetězci poskytl konstantní výsledek pro všechny ostatní hodnoty s plovoucí desetinnou čárkou. Výpočet x 0 může například vést k výsledku 1, i když x je NaN, takže kontrola pouze konečného výsledku by zakryla skutečnost, že výpočet před x 0 vedl k NaN. Obecně je tedy k detekci všech případů, kdy jsou zavedeny NaN, zapotřebí pozdější test pro nastavený neplatný příznak ( další podrobnosti viz definice funkce níže).

V části 6.2 starého standardu IEEE 754-2008 existují dvě anomální funkce (funkce maxNuma minNum, které vracejí maximálně dva operandy, u nichž se očekává, že budou čísly), které upřednostňují čísla-pokud jen jeden z operandů je NaN, pak vrátí se hodnota druhého operandu. IEEE 754-2019 revize nahradila tyto funkce, protože nejsou asociativní (když signalizační NaN se objeví v operand).

Srovnání s NaN

Porovnání s NaN vždy vrátí neuspořádaný výsledek, i když se porovnává se sebou samým. Porovnávací predikáty jsou buď signalizační nebo nesignalizační na tichých operandech NaN; signální verze signalizují neplatnou operaci výjimky pro taková srovnání. Predikáty rovnosti a nerovnosti jsou nesignalizační, takže x  =  x vrací false může být použito k testování, zda x je tichý NaN. Ostatní standardní predikáty porovnání jsou všechny signalizující, pokud obdrží operand NaN. Standard také poskytuje nesignalizační verze těchto dalších predikátů. Predikát určuje, zda je hodnota NaN a nikdy nesignalizuje výjimku, i když x je signalizující NaN. isNaN(x)

Porovnání NaN a jakékoli hodnoty s plovoucí desetinnou čárkou x (včetně NaN a ± ∞)
Srovnání NaN ≥ x NaN ≤ x NaN> x NaN < x NaN = x NaN ≠ x
Výsledek Nepravdivé Nepravdivé Nepravdivé Nepravdivé Nepravdivé Skutečný

Operace generující NaN

Existují tři druhy operací, které mohou vrátit NaN:

  • Většina operací s alespoň jedním operandem NaN.
  • Neurčité formy :
    • Dělení (± 0) / (± 0) a (± ∞) / (± ∞) .
    • Násobení (± 0) × (± ∞) a (± ∞) × (± 0) .
    • Zbývající x  % y, když x je nekonečno nebo y je nula.
    • Sčítání (+∞)+(−∞) , (−∞)+(+∞) a ekvivalentní odčítání (+∞) - (+∞) a (−∞) - (−∞) .
    • Standard má alternativní funkce pro síly:
      • Standardní powfunkce a celočíselná exponentní pownfunkce definují 0 0 , 1 a 0 jako 1 .
      • powrFunkce definuje všechny tři neurčité formy, jako jsou neplatné operace a tak se vrátí NaN.
  • Skutečné operace se složitými výsledky, například:

NaN mohou být také explicitně přiřazeny proměnným, obvykle jako reprezentace chybějících hodnot. Před standardem IEEE programátoři často používali speciální hodnotu (například −99999999) k reprezentaci nedefinovaných nebo chybějících hodnot, ale neexistovala žádná záruka, že budou zpracovávány konzistentně nebo správně.

NaN nejsou nutně generovány ve všech výše uvedených případech. Pokud operace může způsobit výjimku a pasti nejsou maskovány, způsobí místo toho past. Pokud je operandem tichý NaN a také neexistuje žádný signalizující operand NaN, pak neexistuje podmínka výjimky a výsledkem je tichý NaN. Explicitní přiřazení nezpůsobí výjimku ani pro signalizaci NaN.

Tichý NaN

Tiché NaN nebo qNaN nevyvolávají žádné další výjimky, protože se šíří většinou operací. Výjimkou jsou případy, kdy NaN nelze jednoduše předat nezměněné na výstup, například při převodu formátu nebo při určitých porovnávacích operacích.

Signalizace NaN

Signalizační NaN nebo sNaNs jsou speciální formy NaN, které, když jsou spotřebovány většinou operací, by měly zvýšit výjimku neplatné operace a poté, pokud je to vhodné, být „utišeny“ do qNaN, které se pak mohou šířit. Byly zavedeny v IEEE 754 . Existuje několik nápadů, jak by mohly být použity:

  • Vyplnění neinicializované paměti signalizujícími NaN by způsobilo neplatnou operaci výjimky, pokud jsou data použita před její inicializací
  • Použití sNaN jako zástupného symbolu pro složitější objekt , jako například:

Když se vyskytne, obsluha pasti mohla dekódovat sNaN a vrátit index k vypočítanému výsledku. V praxi se tento přístup potýká s mnoha komplikacemi. Zpracování znaménkového bitu NaN u některých jednoduchých operací (jako je absolutní hodnota ) je jiné než u aritmetických operací. Pasti nejsou standardem vyžadovány. Existují další přístupy k tomuto druhu problému, které by byly přenosnější.

Operace užitečného zatížení

IEEE 754-2019 doporučuje implementovat operace getPayload , setPayload a setPayloadSignaling , které standardizují přístup k datovým částem za účelem zefektivnění používání aplikací. Podle podkladového dokumentu IEEE 754-2019 by toto doporučení mělo být interpretováno jako „požadované pro nové implementace, s výhradou zpětné kompatibility“.

Definice funkce

Existují rozdíly v názorech na správnou definici výsledku numerické funkce, která přijímá jako vstup tichý NaN. Jeden pohled je, že NaN by se měla šířit na výstup funkce ve všech případech, aby se šířila indikace chyby. Další pohled, a to obecně podle norem ISO C99 a IEEE 754-2008 , je, že pokud má funkce více argumentů a výstup je jednoznačně určen všemi vstupy, které nejsou NaN (včetně nekonečna), pak by tato hodnota měla být výsledkem. Například například hodnota vrácená hypot(±∞, qNaN)a hypot(qNaN, ±∞)je +∞.

Tento problém je zvláště akutní při umocňování funkci = x y . Výrazy 0 0 , ∞ 0 a 1 jsou považovány za neurčité formy, pokud se vyskytují jako limity (stejně jako ∞ × 0), a otázka, zda by nula až nulový výkon měla být definována jako 1, má rozdělený názor. pow(x, y)

Pokud je výstup považován za nedefinovaný, když je parametr nedefinovaný, pow(1, qNaN)měl by vytvořit qNaN. Nicméně, matematické knihovny mají obvykle vrací 1 pro žádného reálné číslo y , a to i když y je nekonečno . Podobně produkují 1, i když x je 0 nebo nekonečno. Důvodem pro vrácení hodnoty 1 pro neurčité formy bylo, že hodnotu funkcí v singulárních bodech lze brát jako konkrétní hodnotu, pokud je tato hodnota v mezní hodnotě pro všechny, kromě mizivě malé části koule kolem mezní hodnoty parametrů. Verze 2008 IEEE 754 standardu říká, že i oba měli return 1, protože oni se vrátí 1 cokoli jiného se používá namísto klidné NaN. ISO C99 a novější IEEE 754-2008 navíc zvolily specifikaci = 1 místo qNaN; důvod této volby je uveden v odůvodnění: „Obecně platí, že C99 se vyhýbá výsledku NaN, kde je užitečná číselná hodnota ... Výsledkem je +∞, protože všechny velké kladné hodnoty s plovoucí desetinnou čárkou jsou sudá celá čísla.“ pow(1, y) pow(x, 0)pow(1, qNaN)pow(qNaN, 0)pow(−1, ±∞)pow(−2, ∞)

Aby uspokojil ty, kteří chtějí více striktní výklad o tom, jak by měl výkon funkce jednat za rok 2008 standard definuje další dvě výkonové funkce: , kde musí exponent být celé číslo a , které vrátí NaN, když parametr je NaN nebo umocňování by dát neurčitou formu . pown(x, n)powr(x, y)

Celé číslo NaN

Většina celočíselných formátů pevné velikosti nemůže explicitně označovat neplatná data. V takovém případě při převodu NaN na celočíselný typ vyžaduje standard IEEE 754, aby byla signalizována neplatná výjimka operace . Například v Javě takové operace vyvolávají instance java.lang.ArithmeticException. V jazyce C vedou k nedefinovanému chování , ale pokud je příloha F podporována, získá operace „neplatnou“ výjimku s plovoucí desetinnou čárkou (jak vyžaduje standard IEEE) a neurčenou hodnotu.

Perl ‚s Math::BigIntbalíček používá‚NaN‘na výsledek řetězce, které nepředstavují platné celá čísla.

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

Zobrazit

Různé operační systémy a programovací jazyky mohou mít různé řetězcové reprezentace NaN.

nan (C, C++ output)
NaN (ECMAScript, Rust)
NaN% 
NAN (Rust, C, C++ source code)
NaNQ (IBM XL and AIX: Fortran, C++ proposal n2290)
NaNS (ditto)
qNaN
sNaN
1.#SNAN (Excel)
1.#QNAN (Excel)
-1.#IND (Excel)
+nan.0 (Scheme)

Vzhledem k tomu, že v praxi mají kódované NaN znaménko, tichý/signalizační bit a volitelnou „diagnostickou informaci“ (někdy nazývanou užitečná zátěž ), občas je najdeme i v řetězcových reprezentacích NaN. Některé příklady jsou:

  • U jazyků C a C ++ je znakový bit vždy zobrazen funkcemi standardní knihovny (např. -nan), Pokud jsou k dispozici. Neexistuje standardní zobrazení užitečného zatížení ani stavu signalizace, ale klidnou hodnotu NaN konkrétního užitečného zatížení lze buď vytvořit poskytnutím řetězce funkci pro analýzu čísel (např. ), Nebo poskytnutím řetězce sekvence znaků ( nebo pro sNaN), obojí interpretováno způsobem definovaným implementací. nan(char-sequence)strtodnan()nans()
    • GCC a LLVM poskytuje vestavěné implementace nan()a nans(). Analyzují sekvenci znaků jako celé číslo strtoull(nebo ekvivalent jiné velikosti) s detekcí celočíselných základen.
    • Na GNU C Library ‚s float-parser používá char-sekvenční řetězec "blíže neurčené módy". V praxi je tato analýza ekvivalentní GCC/LLVM až pro 64 bitů užitečného zatížení.
    • Newlib neimplementuje nan()analýzu, ale strtod()přijímá hexadecimální formát bez předpony.
    • musl neimplementuje žádnou analýzu užitečného zatížení.

Ne všechny jazyky připouštějí existenci více NaN. Například ECMAScript používá pouze jednu hodnotu NaN.

Kódování

V IEEE 754 standardně vyhovujících formátech s plovoucí desetinnou čárkou jsou NaN identifikovány specifickými, předdefinovanými bitovými vzory jedinečnými pro NaN. Na znaménkovém bitu nezáleží. NaN v binárním formátu jsou reprezentovány exponenciálním polem vyplněným jedničkami (jako jsou hodnoty nekonečna) a některým nenulovým číslem v důležitém poli (aby byly odlišné od nekonečných hodnot). Původní standard IEEE 754 z roku 1985 ( IEEE 754-1985 ) popisoval pouze binární formáty s plovoucí desetinnou čárkou a nespecifikoval, jak má být označen stav signalizace/klid. V praxi nejvýznamnější bit významného pole určoval, zda je NaN signalizační nebo tichý. Výsledkem byly dvě různé implementace s obrácenými významy:

  • většina procesorů (včetně těch z Intel a AMD s x86 rodině, Motorola 68000 rodina je AIM PowerPC rodina, ARM rodina, Sun SPARC rodina, a případně nové MIPS procesory) nastavit signalizaci / tichý bitů na nenulovou pokud je NaN tichý, a na nulu, pokud NaN signalizuje. Na těchto procesorech tedy bit představuje is_quietpříznak;
  • v NaN generovaných PA-RISC a starými MIPS procesory je bit signalizace/klid nulový, pokud je NaN tichý, a nenulový, pokud NaN signalizuje. Na těchto procesorech tedy bit představuje is_signalingpříznak.

Upřednostňován byl první výběr, protože umožňuje implementaci ztišit signalizační NaN pouhým nastavením bitů signalizace/klid na 1. Opačná volba není možná, protože nastavení bitu signalizace/klid na 0 by mohlo přinést nekonečno.

Mezi 2008 a 2019 revize IEEE 754 standardu make formální požadavky a doporučení pro zakódování signalizace / klidovém stavu se.

  • U formátů binární výměny se nejvýznamnější bit pole s významem používá výhradně k rozlišení tichých a signalizujících NaN. Navíc by to měla být is_quietvlajka. To znamená, že tento bit je nenulový, pokud je NaN tichý, a nula, pokud NaN signalizuje.
  • U formátů pro výměnu desetinných čísel, ať už binárních nebo desítkových, je NaN identifikována tak, že je prvních pět bitů kombinačního pole za bitem znaku nastaveno na jedničky. Šestý bit pole je is_signalingvlajka. To znamená, že tento bit je nula, pokud je NaN tichý, a nenulový, pokud NaN signalizuje.

Pro shodu IEEE 754-2008 je význam signalizačního/tichého bitu v nedávných procesorech MIPS nyní konfigurovatelný prostřednictvím pole NAN2008 registru FCSR. Tato podpora je v MIPS Release 3 volitelná a je vyžadována v Release 5.

Stav/hodnota zbývajících bitů významného pole nejsou standardem definovány. Tato hodnota se nazývá 'užitečné zatížení' NaN. Pokud má operace jeden vstup NaN a šíří ho na výstup, mělo by být užitečné zatížení NaN ze vstupního NaN (to není vždy možné u binárních formátů, když je signalizační/klidový stav kódován is_signalingpříznakem, jak je vysvětleno výše ). Pokud existuje více vstupů NaN, mělo by být užitečné zatížení NaN z jednoho ze vstupních NaN; norma neurčuje jaké.

Reference

Standardy

externí odkazy