0

IEEE-754 плаващ визуализатор

Вижте точно как десетично число се съхранява като IEEE-754 float — битове за знак, битове за експонента и битове за мантиса — и защо числа като 0,1 не се съхраняват точно.

Buy Me a Coffee at ko-fi.com
Обработка... 0%
Нормализиране
Изчисляване на отклонение на степента
Разширяващи се битове на мантиса
Готово

Резултат

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

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

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

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