0

IEEE-754-liukulukuvisualisaattori

Katso tarkalleen, miten desimaaliluku tallennetaan IEEE-754-liukulukuna — etumerkkibitti, eksponenttibitit ja mantissabitit — ja miksi lukuja kuten 0,1 ei tallenneta tarkasti.

🔒 Käsitelty kokonaan selaimessasi – mitään tähän kirjoittamaasi ei koskaan ladata.

Käsitellään... 0%
Normalisoidaan
Lasketaan eksponenttiharha
Muodostetaan mantissan bitit
Valmis

Tulos

Jokainen tietokoneen tallentama liukuluku — JavaScriptin numero, C:n float, Pythonin float — koodataan samalla tavalla IEEE 754 -standardin mukaan: yksi etumerkkibitti, lohko eksponenttibittejä ja lohko mantissabittejä (desimaaliosa). Kertatarkkuus (32-bittinen) käyttää yhtä etumerkkibittiä, 8:aa eksponenttibittiä ja 23:a mantissabittiä; kaksinkertainen tarkkuus (64-bittinen), muoto melkein jokaisen kielen oletuslukutyypin taustalla, käyttää yhtä etumerkkibittiä, 11:tä eksponenttibittiä ja 52:a mantissabittiä. Tämä työkalu ottaa minkä tahansa syöttämäsi desimaaliluvun, koodaa sen jommallakummalla leveydellä käyttäen selaimen omaa DataView/ArrayBuffer-liukulukukooderia — samaa konetta, jolla oma koodisi todellisuudessa toimii — ja värittää jokaisen bitin sen mukaan, mihin alueeseen se kuuluu.

Itse koodaus etenee kolmessa vaiheessa, ja tämä työkalu käy läpi ne kaikki sen sijaan, että näyttäisi vain lopulliset bitit. Ensimmäinen, normalisointi: luku kirjoitetaan muotoon 1.mantissa × 2^eksponentti, jossa binääripisteen edessä on täsmälleen yksi nollasta poikkeava numero (liian pienet luvut saavat subnormaalikäsittelyn, jossa ei ole implisiittistä johtavaa ykköstä). Toinen, eksponenttiharha: koska eksponenttikentän on tallennettava sekä positiiviset että negatiiviset eksponentit etumerkittömänä lukuna, kiinteä harha (127 kertatarkkuudelle, 1023 kaksinkertaiselle) lisätään ennen kuin kenttä kirjoitetaan binäärimuodossa. Kolmas, desimaaliosa muodostetaan bitti bitiltä klassisella “kerro kahdella, ota kokonaislukuosa seuraavaksi bitiksi, pidä jakojäännös” -menetelmällä — toistetaan, kunnes mantissakenttä on täynnä, jolloin ylijäävät bitit ratkaisevat, pyöristyykö tulos ylös vai alas (pyöristys puolesta lähimpään, IEEE-754-oletus).

Tämä selittää tarkasti, miksi niinkin tavallinen luku kuin 0,1 ei tallennu tarkasti. Binäärijärjestelmässä 0,1 on päättymätön jaksollinen murtoluku (0,0001100110011…, ikuisesti), joten mikään äärellinen mantissa ei voi esittää sitä tarkasti — se on pyöristettävä jossain kohtaa. Syötä 0,1 32-bittisenä liukulukuna ja lue bitit takaisin, etkä saa takaisin 0,1:tä: saat tarkalleen 0,100000001490116119384765625. Kaksinkertaisessa tarkkuudessa on 29 mantissabittiä enemmän käytössä, joten sen pyöristysvirhe on paljon pienempi, mutta se ei ole nollakaan — 0,1 64-bittisenä double-lukuna on tarkalleen 0,1000000000000000055511151231257827021181583404541015625. Tämä työkalu laskee tuon tarkan tallennetun arvon suurten kokonaislukujen aritmetiikalla (ei liukulukuoikoteitä), joten eroa syöttämäsi ja sen välillä, mitä laitteisto todella pitää, ei koskaan piiloteta tai arvioida.

Erikoisarvot saavat tarkat, varatut bittikuviot normaalin koodauksen sijaan: nolla ja negatiivinen nolla sisältävät pelkkiä nollia eksponentti- ja mantissabiteissä (vain etumerkkibitti eroaa), ±ääretön sisältää pelkkiä ykkösiä eksponenttibiteissä ja nollia mantissabiteissä, ja NaN sisältää pelkkiä ykkösiä eksponenttibiteissä ja vähintään yhden ykkösen mantissabiteissä. Kaikki täällä toimii paikallisesti selaimessasi — mitään syöttämääsi ei ladata minnekään — mikä tekee tästä turvallisen paikan rakentaa todellista intuitiota liukulukuongelmista: miksi `0.1 + 0.2 !== 0.3` lähes jokaisessa ohjelmointikielessä, miksi float32-tekstuurit grafiikkakoodissa menettävät tarkkuutta tavalla, jota float64 ei menettäisi, ja miksi talouskoodin tulisi yleensä välttää binääristä liukulukua kokonaan.