IEEE-754 plavajoči vizualizator
Oglejte si, kako natančno je decimalno število shranjeno kot IEEE-754 float – bit predznaka, bit eksponenta in bit mantise – in zakaj števila, kot je 0,1, niso shranjena natančno.
Rezultat
Vsako število s plavajočo vejico, ki ga računalnik shrani – število JavaScript, plavajoče število C, plavajoče število Python – je po standardu IEEE 754 kodirano na enak način: en bit predznaka, blok bitov eksponenta in blok bitov mantise (ulomek). Enojna natančnost (32-bitna) uporablja 1 predznakovni bit, 8 eksponentnih bitov in 23 mantisinih bitov; dvojna natančnost (64-bit), format za privzetim tipom števila v skoraj vseh jezikih, uporablja 1 predznakovni bit, 11 eksponentnih bitov in 52 mantisinih bitov. To orodje sprejme katero koli decimalno število, ki ga vnesete, ga kodira v katero koli širino z uporabo brskalnikovega lastnega kodirnika podatkov DataView/ArrayBuffer – isti stroj, na katerem vaša koda dejansko teče – in obarva vsak bit glede na to, kateri regiji pripada.
Samo kodiranje sledi trem korakom in to orodje se sprehodi skozi vse, namesto da bi prikazalo le zadnje delce. Prvič, normalizacija: število je prepisano kot 1.mantisa × 2^eksponent, z natanko eno neničelno števko pred binarno točko (števila, premajhna za to, dobijo subnormalno obravnavo, brez implicitnega vodilnega 1). Drugič, pristranskost eksponenta: ker mora polje eksponenta shraniti pozitivne in negativne eksponente kot število brez predznaka, se doda fiksna pristranskost (127 za enojno natančnost, 1023 za dvojno), preden se polje izpiše v dvojiški obliki. Tretjič, frakcijska mantisa se razširi malo za bitom s klasično metodo »pomnoži z dve, vzemi celo število kot naslednji bit, obdrži preostanek« — ponavlja se, dokler ni polje mantise polno, na kateri točki preostali biti odločijo, ali rezultat zaokroži navzgor ali navzdol (zaokroži od pol do sodo, privzeto IEEE-754).
Prav zaradi tega tako navadna številka, kot je 0,1, ni natančno shranjena. V dvojiški obliki je 0,1 ponavljajoči se ulomek (0,0001100110011 ..., za vedno), zato ga nobena končna mantisa ne more natančno zadržati - nekje ga je treba zaokrožiti. Kodirajte 0.1 kot 32-bitno število s plavajočo vrednostjo in preberite bite nazaj, pa ne boste dobili 0.1 nazaj: dobili boste točno 0.100000001490116119384765625. Dvojna natančnost ima še 29 mantisinih bitov za delo, zato je njena napaka zaokroževanja veliko manjša, vendar tudi ni nič — 0,1 kot 64-bitna dvojnica je natanko 0,100000000000000055511151231257827021181583404541015625. To orodje izračuna tisto natančno shranjeno vrednost z aritmetiko velikega celega števila (brez bližnjic s plavajočo vejico), tako da vrzel med tem, kar ste vnesli, in tem, kar strojna oprema dejansko hrani, ni nikoli skrita ali približna.
Posebne vrednosti dobijo natančne, rezervirane bitne vzorce namesto običajnega kodiranja: nič in negativna ničla imata vse ničelne eksponente in bite mantise (razlikuje se le bit predznaka), ±Infinity ima vse ena eksponentne bite z ničelno mantiso in NaN ima vse ena eksponentne bite z vsaj enim nastavljenim bitom mantise. Vse tukaj deluje lokalno v vašem brskalniku – nič, kar vtipkate, ni nikamor naloženo – zaradi česar je to varno mesto za ustvarjanje resnične intuicije za hrošče s plavajočo vejico: zakaj `0,1 + 0,2 !== 0,3` v skoraj vseh programskih jezikih, zakaj teksture float32 v grafični kodi izgubijo natančnost, ki je float64 ne bi, in zakaj bi se morala finančna koda na splošno izogibati binarni plavajoči vejici skupaj.