0

Wizualizator pływający IEEE-754

Zobacz dokładnie, jak liczba dziesiętna jest przechowywana jako liczba zmiennoprzecinkowa IEEE-754 — bit znaku, bity wykładnika i bity mantysy — i dlaczego liczby takie jak 0,1 nie są przechowywane dokładnie.

Buy Me a Coffee at ko-fi.com
Przetwarzanie... 0%
Normalizowanie
Obliczanie obciążenia wykładnika
Rozszerzanie bitów mantysy
Gotowe

Wynik

Każda liczba zmiennoprzecinkowa przechowywana w komputerze — liczba JavaScript, liczba zmiennoprzecinkowa C, liczba zmiennoprzecinkowa w Pythonie — jest kodowana w ten sam sposób w standardzie IEEE 754: jeden bit znaku, blok bitów wykładnika i blok bitów mantysy (ułamka). Pojedyncza precyzja (32-bitowa) wykorzystuje 1 bit znaku, 8 bitów wykładnika i 23 bity mantysy; podwójna precyzja (64-bitowa), format domyślnego typu liczbowego w prawie każdym języku, wykorzystuje 1 bit znaku, 11 bitów wykładnika i 52 bity mantysy. To narzędzie pobiera dowolną wpisaną liczbę dziesiętną, koduje ją w dowolnej szerokości przy użyciu własnego kodera zmiennoprzecinkowego DataView/ArrayBuffer przeglądarki — tej samej maszyny, na której faktycznie działa Twój kod — i koloruje każdy bit według regionu, do którego należy.

Samo kodowanie składa się z trzech etapów, a to narzędzie przeprowadza je wszystkie, zamiast pokazywać tylko ostatnie bity. Po pierwsze, normalizacja: liczba jest przepisywana jako 1.mantysa × 2^wykładnik, z dokładnie jedną niezerową cyfrą przed przecinkiem binarnym (liczby za małe, aby to zrobić, są zamiast tego traktowane jako subnormalne, bez ukrytej początkowej 1). Po drugie, obciążenie wykładnika: ponieważ pole wykładnika musi przechowywać wykładniki dodatnie i ujemne jako liczbę bez znaku, przed zapisaniem pola w formacie binarnym dodawane jest stałe obciążenie (127 dla pojedynczej precyzji, 1023 dla podwójnej). Po trzecie, mantysa ułamkowa jest rozwijana krok po kroku za pomocą klasycznej metody „pomnóż przez dwa, weź część całkowitą jako następny bit, resztę zachowaj” – powtarza się, aż pole mantysy się zapełni, i w tym momencie pozostałe bity decydują, czy wynik zaokrągli się w górę, czy w dół (zaokrąglenie od połowy do parzystej, domyślnie IEEE-754).

Właśnie dlatego liczba tak zwyczajna jak 0,1 nie jest zapisywana dokładnie. W systemie binarnym 0,1 to powtarzający się ułamek (0,0001100110011…, na zawsze), więc żadna skończona mantysa nie jest w stanie tego dokładnie zapisać — trzeba to gdzieś zaokrąglić. Zakoduj 0,1 jako 32-bitową liczbę zmiennoprzecinkową i odczytaj bity z powrotem, a nie otrzymasz z powrotem 0,1: otrzymasz dokładnie 0,100000001490116119384765625. Podwójna precyzja ma do pracy 29 dodatkowych bitów mantysy, więc błąd zaokrąglenia jest znacznie mniejszy, ale też nie wynosi zero — 0,1 w przypadku 64-bitowego podwójnego wynosi dokładnie 0,1000000000000000055511151231257827021181583404541015625. To narzędzie oblicza dokładnie zapisaną wartość za pomocą arytmetyki dużych liczb całkowitych (bez skrótów zmiennoprzecinkowych), więc różnica między tym, co wpisałeś, a tym, co faktycznie przechowuje sprzęt, nigdy nie jest ukrywana ani przybliżana.

Wartości specjalne uzyskują dokładne, zarezerwowane wzorce bitowe zamiast normalnego kodowania: zero i zero ujemne mają całkowicie zerowe bity wykładnika i mantysy (różni się tylko bit znaku), ±Infinity ma wszystkie bity wykładnika z mantysą zerową, a NaN ma wszystkie bity wykładnika z co najmniej jednym ustawionym bitem mantysy. Wszystko tutaj działa lokalnie w Twojej przeglądarce — nic, co wpiszesz, nie zostanie nigdzie przesłane — co sprawia, że ​​jest to bezpieczne miejsce do zbudowania prawdziwej intuicji pod kątem błędów zmiennoprzecinkowych: dlaczego „0,1 + 0,2 !== 0,3” w prawie każdym języku programowania, dlaczego tekstury float32 w kodzie graficznym tracą precyzję, czego nie zrobiłby float64 i dlaczego kod finansowy powinien w ogóle unikać binarnych zmiennoprzecinkowych.