IEEE-754 plūduriuojantis vizualizatorius
Sužinokite, kaip tiksliai dešimtainis skaičius išsaugomas kaip IEEE-754 float – ženklo bitai, eksponento bitai ir mantisos bitai – ir kodėl tokie skaičiai kaip 0,1 nėra saugomi tiksliai.
Rezultatas
Kiekvienas kompiuterio saugomas slankiojo kablelio skaičius – „JavaScript“ skaičius, „C float“, „Python“ slankiklis – yra užkoduotas taip pat pagal IEEE 754: vienas ženklo bitas, eksponento bitų blokas ir mantisos (trupnės) bitų blokas. Vieno tikslumo (32 bitai) naudoja 1 ženklo bitą, 8 eksponento bitus ir 23 mantisos bitus; dvigubo tikslumo (64 bitų), formato, kuris yra beveik visų kalbų numatytasis skaičių tipas, naudojamas 1 ženklo bitas, 11 eksponento bitų ir 52 mantisos bitai. Šis įrankis paima bet kurį jūsų įvestą dešimtainį skaičių, užkoduoja jį bet kuriuo pločiu, naudodamas naršyklės „DataView“ / „ArrayBuffer“ plūduriuojančią kodavimo priemonę – tą pačią mašiną, kurioje iš tikrųjų veikia jūsų kodas – ir nuspalvina kiekvieną bitą pagal regioną, kuriam jis priklauso.
Pats kodavimas atliekamas trimis etapais, o šis įrankis atlieka visus juos, o ne tik rodo paskutinius bitus. Pirma, normalizavimas: skaičius perrašomas kaip 1.mantisa × 2^ eksponentas, o prieš dvejetainį tašką yra lygiai vienas skaitmuo, kuris nėra nulis (tam per mažiems skaičiams taikomas nenormalus traktavimas, be numanomo 1 priekyje). Antra, eksponento poslinkis: kadangi eksponento lauke tiek teigiami, tiek neigiami eksponentai turi būti saugomi kaip nežymėtas skaičius, prieš išrašant lauką dvejetainiu formatu, pridedamas fiksuotas poslinkis (127 vienkartiniam tikslumui, 1023 dvigubam). Trečia, trupmeninė mantisa po truputį plečiama naudojant klasikinį metodą „padaugink iš dviejų, sveikąją dalį imk kaip kitą bitą, pasilik likutį“ – kartojama tol, kol mantisos laukas užpildomas, o tada likę bitai nusprendžia, ar rezultatas apvalinamas aukštyn ar žemyn (apvalinama pusė iki lygaus, IEEE-754 numatytasis).
Būtent todėl toks įprastas skaičius kaip 0,1 nėra tiksliai išsaugomas. Dvejetainėje sistemoje 0,1 yra pasikartojanti trupmena (0,0001100110011…, amžinai), todėl jokia baigtinė mantisa negali jos tiksliai laikyti – ji turi būti kažkur suapvalinta. Užkoduokite 0.1 kaip 32 bitų slankųjį ir skaitykite bitus atgal, o 0.1 atgal negausite: gausite tiksliai 0.100000001490116119384765625. Dvigubas tikslumas turi dar 29 mantisos bitus, todėl jo apvalinimo paklaida yra daug mažesnė, tačiau ji taip pat nėra nulis – 0,1, nes 64 bitų dvigubas lygis yra lygiai 0,10000000000000000555111512312578270211815410456. Šis įrankis apskaičiuoja tikslią išsaugotą vertę naudodamas didelių sveikųjų skaičių aritmetiką (be slankiojo kablelio sparčiųjų klavišų), todėl atotrūkis tarp to, ką įvedėte, ir to, ką iš tikrųjų saugo aparatinė įranga, niekada nėra paslėptas ar apytikslis.
Ypatingos reikšmės gauna tikslius, rezervuotus bitų šablonus, o ne įprastą kodavimą: nulis ir neigiamas nulis turi visų nulių eksponentus ir mantisos bitus (skiriasi tik ženklo bitai), ± Infinity turi vieno eksponento bitus, kurių mantisa yra nulinė, o NaN turi visus vieno eksponento bitus su bent vienu mantisos bitų rinkiniu. Viskas čia veikia lokaliai jūsų naršyklėje – nieko, ką įvedėte, niekur neįkeliama – todėl tai yra saugi vieta sukurti tikrą intuiciją slankiojo kablelio klaidoms: kodėl `0,1 + 0,2 !== 0,3` beveik visose programavimo kalbose, kodėl float32 tekstūros grafiniame kode praranda tikslumą, kurio float64 neišvengtų, ir kodėl paprastai turėtų vengti slankiojo taško dvejetainis finansinis kodas.