0

Візуалізатор IEEE-754

Подивіться, як саме десяткове число зберігається у форматі IEEE-754 — біт знаку, біти експоненти та біти мантиси — і чому числа на кшталт 0,1 не зберігаються точно.

🔒 Обробляється повністю у вашому браузері — те, що ви тут вводите, ніколи не вивантажується.

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

Результат

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

Саме кодування складається з трьох кроків, і цей інструмент показує кожен із них, а не лише кінцеві біти. Перший — нормалізація: число подається як 1.мантиса × 2^експонента, з рівно однією ненульовою цифрою перед двійковою крапкою (для занадто малих чисел замість цього застосовується субнормальна форма, без неявної провідної одиниці). Другий — зсув експоненти: оскільки поле експоненти має зберігати як додатні, так і від’ємні експоненти як беззнакове число, додається фіксований зсув (127 для одинарної точності, 1023 для подвійної), перш ніж поле запишеться у двійковому вигляді. Третій — дробова мантиса розкладається порозрядно класичним методом «помножити на два, взяти цілу частину як наступний біт, залишити остачу» — і так до заповнення поля мантиси, після чого залишкові біти визначають, чи округлювати вгору, чи вниз (банківське округлення, типове для IEEE-754).

Саме тому таке звичайне число, як 0,1, не зберігається точно. У двійковій системі 0,1 — це періодичний дріб (0.0001100110011…, нескінченний), тому жодна скінченна мантиса не може зберегти його точно — десь доводиться округлювати. Закодуйте 0,1 як 32-бітний float і прочитайте біти назад — ви отримаєте не 0,1, а рівно 0,100000001490116119384765625. Подвійна точність має на 29 бітів мантиси більше, тож її похибка округлення значно менша, але не нульова — 0,1 як 64-бітний double дорівнює рівно 0,1000000000000000055511151231257827021181583404541015625. Цей інструмент обчислює точне збережене значення за допомогою довгої цілочислової арифметики (без спрощень із плаваючою комою), тому різниця між тим, що ви ввели, і тим, що насправді зберігає обладнання, ніколи не приховується і не апроксимується.

Особливі значення отримують точні, зарезервовані бітові комбінації, а не звичайне кодування: нуль і від’ємний нуль мають усі нулі в полях експоненти та мантиси (відрізняються лише бітом знаку), ±Infinity має всі одиниці в полі експоненти та нульову мантису, а NaN — усі одиниці в полі експоненти та хоча б один біт мантиси встановлено. Усе працює локально у вашому браузері — жодне введене значення нікуди не надсилається — тож це безпечне місце, щоб виробити справжню інтуїцію щодо помилок із плаваючою комою: чому `0.1 + 0.2 !== 0.3` майже в усіх мовах програмування, чому float32-текстури у графічному коді втрачають точність, якої б не втрачав float64, і чому у фінансовому коді зазвичай варто взагалі уникати двійкової плаваючої коми.