0

IEEE-754 Float Visualizer

Katso tarkalleen, kuinka desimaaliluku tallennetaan IEEE-754 floatina – etumerkkibitit, eksponenttibitit ja mantissabitit – ja miksi lukuja, kuten 0,1, ei tallenneta tarkasti.

Buy Me a Coffee at ko-fi.com
Käsitellään... 0%
Normalisoidaan
Laskennan eksponenttiharha
Laajenevat mantissanpalat
Valmis

Tulos

Jokainen tietokoneen tallentama liukulukuluku – JavaScript-luku, C float, Python float – on koodattu samalla tavalla IEEE 754:ssä: yksi merkkibitti, eksponenttibittien lohko ja mantissa- (murto-)bittien lohko. Yksittäinen tarkkuus (32-bittinen) käyttää 1 etumerkkibittiä, 8 eksponenttibittiä ja 23 mantissabittiä; kaksinkertainen tarkkuus (64-bittinen), lähes jokaisen kielen oletusnumerotyypin takana oleva muoto, käyttää 1 merkkibittiä, 11 eksponenttibittiä ja 52 mantissabittiä. Tämä työkalu ottaa minkä tahansa kirjoittamasi desimaaliluvun, koodaa sen kummalla tahansa leveydellä käyttämällä selaimen omaa DataView/ArrayBuffer float-enkooderia – samaa koneistoa, jolla koodisi todella toimii – ja värittää jokaisen bitin sen alueen mukaan, johon se kuuluu.

Itse koodaus seuraa kolmea vaihetta, ja tämä työkalu käy läpi ne kaikki sen sijaan, että näyttäisi vain viimeiset bitit. Ensinnäkin normalisointi: luku kirjoitetaan uudelleen muotoon 1.mantissa × 2^eksponentti, jossa on täsmälleen yksi nollasta poikkeava numero ennen binääripistettä (tälle liian pienet luvut saavat sen sijaan alinormaalin käsittelyn, ilman implisiittistä alkulukua 1). Toiseksi eksponenttipoikkeama: koska eksponenttikenttään on tallennettava sekä positiiviset että negatiiviset eksponentit etumerkittömänä lukuna, kiinteä poikkeama (127 yksittäiselle tarkkuudelle, 1023 tuplatarkkuudelle) lisätään ennen kentän kirjoittamista binäärimuodossa. Kolmanneksi murto-osa mantissaa laajennetaan bitti kerrallaan perinteisellä "kerro kahdella, ota kokonaislukuosa seuraavaksi bitiksi, säilytä jäännös" -menetelmällä - toistetaan, kunnes mantissakenttä on täynnä, jolloin jäljelle jääneet bitit päättävät, pyöristetäänkö tulos ylös vai alas (pyöristä puolitasoon, IEEE-754 oletusarvo).

Juuri tästä syystä niinkin tavallista numeroa kuin 0,1 ei tallenneta tarkasti. Binäärimuodossa 0,1 on toistuva murto-osa (0,0001100110011…, ikuisesti), joten mikään äärellinen mantissa ei voi pitää sitä tarkasti - se on pyöristettävä jossain. Koodaa 0.1 32-bittiseksi floatiksi ja lue bitit takaisin, etkä saa 0.1:tä takaisin: saat täsmälleen 0.100000001490116119384765625. Kaksinkertaisella tarkkuudella on 29 mantissabittiä lisää, joten sen pyöristysvirhe on paljon pienempi, mutta se ei myöskään ole nolla - 0,1, koska 64-bittinen tupla on täsmälleen 0,100000000000000005551111512312578270211815410456. Tämä työkalu laskee tarkan tallennetun arvon isojen kokonaislukujen aritmetiikalla (ei liukulukupikanäppäimiä), joten eroa kirjoittamasi ja laitteiston todellisuudessa säilyttämän välillä ei koskaan piiloteta tai arvioida.

Erikoisarvot saavat tarkat, varatut bittikuviot normaalin koodauksen sijaan: nollassa ja negatiivisessa nollassa on kaikki nolla-eksponentti- ja mantissabitit (vain etumerkkibitti eroaa), ±Infinityssä on kaikki yksi eksponenttibitit, joiden mantissa on nolla, ja NaN:ssä on kaikki yksi eksponenttibitit, joissa on vähintään yksi mantissabitti. Kaikki täällä toimii paikallisesti selaimessasi – mitään kirjoittamaasi ei ladata minnekään – mikä tekee tästä turvallisen paikan rakentaa todellinen intuitio liukulukuvirheille: miksi `0.1 + 0.2 !== 0.3` lähes kaikilla ohjelmointikielillä, miksi float32-tekstuurit grafiikkakoodissa menettävät tarkkuutta, jota float64 ei välttäisi, ja miksi kelluvapistebinaarisen koodin pitäisi yleensä välttää.