0

Визуализатор на IEEE-754 числа с плаваща запетая

Вижте точно как едно десетично число се записва като IEEE-754 число с плаваща запетая — знаков бит, битове за експонента и битове за мантиса — и защо числа като 0.1 не се пазят точно.

🔒 Обработва се изцяло във вашия браузър - нищо, което въвеждате тук, никога не се качва.

Обработка... 0%
Нормализиране
Изчисляване на отместването на експонентата
Разширяване на битовете на мантисата
Готово

Резултат

Всяко число с плаваща запетая, което компютърът съхранява — JavaScript число, C float, Python float — се кодира по един и същ начин според IEEE 754: един знаков бит, блок от битове за експонента и блок от битове за мантиса (дробната част). Единичната точност (32 бита) използва 1 знаков бит, 8 бита за експонента и 23 бита за мантиса; двойната точност (64 бита), форматът зад типа число по подразбиране на почти всеки език, използва 1 знаков бит, 11 бита за експонента и 52 бита за мантиса. Този инструмент приема въведено от вас десетично число, кодира го във всяка от двете ширини с помощта на вградения в браузъра DataView/ArrayBuffer енкодер за числа с плаваща запетая — същият механизъм, на който реално работи вашият код — и оцветява всеки бит според областта, към която принадлежи.

Самото кодиране следва три стъпки и този инструмент преминава през всички тях, вместо просто да показва крайните битове. Първо, нормализация: числото се представя като 1.мантиса × 2^степен, с точно една ненулева цифра преди двоичната запетая (твърде малките за това числа се третират като субнормални, без неявна водеща единица). Второ, отместване на експонентата: тъй като полето за експонента трябва да съхранява както положителни, така и отрицателни степени като беззнаково число, преди записа му в двоичен вид към стойността се добавя фиксирано отместване (127 за единична точност, 1023 за двойна). Трето, дробната мантиса се разширява бит по бит чрез класическия метод „умножаваме по две, цялата част става следващ бит, остатъкът запазваме“ — повтаря се, докато полето за мантиса се запълни, след което оставащите битове определят дали резултатът се закръгля нагоре или надолу (закръгляне към най-близкото четно, по подразбиране в IEEE-754).

Точно затова едно съвсем обикновено число като 0.1 не се пази точно в паметта. В двоичен вид 0.1 е безкрайна периодична дроб (0.0001100110011…, до безкрай), така че никоя крайна мантиса не може да го побере точно — някъде трябва да се закръгли. Кодирайте 0.1 като 32-битово число и прочетете битовете обратно — не получавате обратно 0.1: получавате точно 0.100000001490116119384765625. Двойната точност разполага с 29 бита повече за мантисата, така че грешката ѝ от закръгляне е далеч по-малка, но не е нулева — 0.1 като 64-битово double е точно 0.1000000000000000055511151231257827021181583404541015625. Този инструмент изчислява тази точна съхранена стойност с целочислена аритметика с голяма точност (без съкращения с плаваща запетая), така че разликата между въведеното от вас и това, което хардуерът реално пази, никога не е скрита или приблизителна.

Специалните стойности получават точни, запазени битови комбинации вместо нормално кодиране: нулата и отрицателната нула имат всички битове за експонента и мантиса нулеви (различават се само по знаковия бит), ±Infinity има всички битове за експонента единици и напълно нулева мантиса, а NaN има всички битове за експонента единици и поне един бит на мантисата зададен. Всичко тук работи локално в браузъра ви — нищо от въведеното не се качва никъде — което прави това безопасно място за изграждане на реална интуиция за проблеми с плаваща запетая: защо `0.1 + 0.2 !== 0.3` в почти всеки програмен език, защо float32 текстурите в графичния код губят точност, която float64 би запазил, и защо финансовият код по принцип трябва да избягва изцяло двоичната плаваща запетая.