IEEE-754 Lebegőpontos Vizualizáló
Nézze meg pontosan, hogyan tárolódik el egy tizedestört IEEE-754 lebegőpontos számként — előjelbit, exponensbitek és mantissza bitek —, és miért nem lehet pontosan eltárolni az olyan számokat, mint a 0,1.
🔒 Teljesen a böngészőjében dolgozzák fel – soha semmi, amit itt beírt, nem kerül feltöltésre.
Eredmény
Minden lebegőpontos szám, amit a számítógép tárol — egy JavaScript szám, egy C float, egy Python float — ugyanúgy kódolódik az IEEE 754 szabvány szerint: egy előjelbit, egy blokk exponensbit és egy blokk mantissza (törtrész) bit. Az egyszeres pontosság (32 bit) 1 előjelbitet, 8 exponensbitet és 23 mantissza bitet használ; a kétszeres pontosság (64 bit), amely szinte minden nyelv alapértelmezett számtípusának hátterében áll, 1 előjelbitet, 11 exponensbitet és 52 mantissza bitet használ. Ez az eszköz fogja az Ön által beírt tizedestörtet, kódolja bármelyik bitszélességgel a böngésző saját DataView/ArrayBuffer float kódolójával — ugyanazt a mechanizmust használva, amin a kódja valójában fut —, és minden bitet színezve jelenít meg aszerint, hogy melyik tartományba tartozik.
A kódolás maga három lépést követ, és ez az eszköz mindegyiken végigmegy, ahelyett hogy csupán a végső biteket mutatná. Először a normalizálás: a szám átíródik 1.mantissza × 2^kitevő alakba, pontosan egy nullától különböző számjeggyel a bináris pont előtt (a túl kicsi számok ehelyett a szubnormális kezelést kapják, implicit vezető 1-es nélkül). Másodszor az exponenseltolás: mivel az exponens mezőnek pozitív és negatív kitevőket is előjel nélküli számként kell tárolnia, egy rögzített eltolást (127 az egyszeres pontosságnál, 1023 a kétszeresnél) hozzáadunk, mielőtt a mezőt binárisan kiírnánk. Harmadszor a törtrész mantissza bitenkénti kibontása a klasszikus „szorozzuk meg kettővel, vegyük az egész részt következő bitként, tartsuk meg a maradékot” módszerrel — ismételve, amíg a mantissza mező meg nem telik, ekkor a maradék bitek döntik el, hogy az eredmény felfelé vagy lefelé kerekül-e (kerekítés a legközelebbi párosra, az IEEE-754 alapértelmezése).
Pontosan ezért nem tárolható egzakt módon egy olyan hétköznapi szám, mint a 0,1. A bináris rendszerben a 0,1 egy végtelen szakaszos tört (0,0001100110011…, örökké), így egyetlen véges mantissza sem tudja pontosan reprezentálni — valahol le kell kerekíteni. Kódolja a 0,1-et 32 bites floatként és olvassa vissza a biteket, és nem 0,1-et kap vissza, hanem pontosan 0,100000001490116119384765625-öt. A kétszeres pontosságnak 29-cel több mantissza bit áll rendelkezésére, így a kerekítési hibája jóval kisebb, de az sem nulla — a 0,1 mint 64 bites double pontosan 0,1000000000000000055511151231257827021181583404541015625. Ez az eszköz ezt az egzakt tárolt értéket nagy egész aritmetikával számolja ki (lebegőpontos trükkök nélkül), így a rés a beírt szám és a hardver által ténylegesen megőrzött érték között soha nem rejtett vagy közelítő jellegű.
A speciális értékek egzakt, fenntartott bitmintákat kapnak a szokásos kódolás helyett: a nulla és a negatív nulla esetében az exponens- és a mantissza bitek mind nullák (csak az előjelbit tér el), a ±végtelen esetében az exponens bitek mind egyesek, a mantissza bitek mind nullák, a NaN esetében pedig az exponens bitek mind egyesek, és legalább egy mantissza bit be van állítva. Minden itt, helyben a böngészőjében fut — semmi, amit begépel, nem kerül feltöltésre sehová —, így ez biztonságos hely valódi megérzések kialakítására a lebegőpontos hibákról: miért 0.1 + 0.2 !== 0.3 szinte minden programnyelvben, miért veszítenek pontosságot a float32 textúrák a grafikai kódban, amit a float64 nem tenne, és miért érdemes a pénzügyi kódokban általában teljesen elkerülni a bináris lebegőpontos számokat.