IEEE-754 Float Visualizer
Podívejte se přesně, jak je desetinné číslo uloženo jako IEEE-754 float – znaménkový bit, exponentní bity a bity mantisy – a proč čísla jako 0,1 nejsou uložena přesně.
Výsledek
Každé číslo s plovoucí desetinnou čárkou, které počítač ukládá – číslo JavaScriptu, C float, Python float – je zakódováno stejným způsobem podle IEEE 754: jeden bit znaménka, blok bitů exponentů a blok bitů mantisy (zlomek). Jednoduchá přesnost (32 bitů) používá 1 bit znaménka, 8 bitů exponentů a 23 bitů mantisy; dvojitá přesnost (64 bitů), formát za standardním typem čísel téměř každého jazyka, používá 1 bit znaménka, 11 bitů exponentů a 52 bitů mantisy. Tento nástroj převezme jakékoli desetinné číslo, které napíšete, zakóduje je v libovolné šířce pomocí vlastního kodéru DataView/ArrayBuffer v prohlížeči – stejný stroj, na kterém váš kód skutečně běží – a obarví každý bit podle oblasti, do které patří.
Samotné kódování probíhá ve třech krocích a tento nástroj je všechny projde, místo aby jen ukázal poslední bity. Za prvé, normalizace: číslo je přepsáno jako 1.mantisa × 2^exponent, s přesně jednou nenulovou číslicí před binárním bodem (čísla, která jsou na to příliš malá, dostanou místo toho subnormální zpracování, bez implicitního počátečního 1). Za druhé, zkreslení exponentů: protože pole exponentů musí ukládat kladné i záporné exponenty jako číslo bez znaménka, je před zapsáním pole binárně přidáno pevné zkreslení (127 pro jednoduchou přesnost, 1023 pro dvojitou přesnost). Za třetí, zlomková mantisa je rozšiřována bit po bitu klasickou metodou „vynásobte dvěma, vezměte celočíselnou část jako další bit, ponechte si zbytek“ — opakuje se, dokud není pole mantisy plné, v tomto okamžiku zbývající bity rozhodnou, zda se výsledek zaokrouhlí nahoru nebo dolů (zaokrouhlení na půl na sudé, výchozí IEEE-754).
To je přesně důvod, proč tak obyčejné číslo jako 0,1 není uloženo přesně. Ve dvojkové soustavě je 0,1 opakující se zlomek (0,0001100110011…, navždy), takže ji žádná konečná mantisa nedokáže přesně udržet – musí být někde zaokrouhlena. Kódujte 0.1 jako 32bitový float a čtěte bity zpět a 0.1 nedostanete zpět: dostanete přesně 0,100000001490116119384765625. Dvojitá přesnost má pro práci o 29 bitů mantisy více, takže její zaokrouhlovací chyba je mnohem menší, ale není ani nulová — 0,1 jako 64bitová dvojka je přesně 0,10000000000000005551115123125782702118151014044551034046 Tento nástroj vypočítá přesnou uloženou hodnotu pomocí aritmetiky velkých celých čísel (žádné zkratky s plovoucí desetinnou čárkou), takže mezera mezi tím, co jste zadali, a tím, co hardware skutečně uchovává, není nikdy skryta ani aproximována.
Speciální hodnoty získávají přesné, vyhrazené bitové vzory spíše než normální kódování: nula a záporná nula mají exponent a mantisu s nulou (liší se pouze bit znaménka), ±Infinity má bity s jedním exponentem s mantisou s nulou a NaN má bity s jedním exponentem s alespoň jednou nastavenou mantisou. Vše zde běží lokálně ve vašem prohlížeči – nic, co píšete, se nikam nenahrává – což z něj dělá bezpečné místo pro budování skutečné intuice pro chyby s plovoucí desetinnou čárkou: proč `0.1 + 0.2 !== 0.3` v téměř každém programovacím jazyce, proč textury float32 v grafickém kódu ztrácejí přesnost, kterou by float64 neměl, a proč by se finanční kód měl obecně vyhýbat binárnímu.