Знаменитий приклад 0.1 + 0.2 !== 0.3, який спантеличує майже кожного початківця в програмуванні, — не помилка мови програмування, а прямий наслідок того, як стандарт IEEE 754 представляє дробові числа у двійковій системі.
Три частини числа з рухомою комою
Число за IEEE 754 зберігається як три компоненти: знак (додатне чи від'ємне), мантиса (значущі цифри числа) і порядок (степінь, на яку зсувається кома). Це схоже на наукову нотацію: 1.5 × 10², тільки в двійковій системі.
Чому 0.1 не можна точно представити у двійковій системі
0.1 у десятковій системі — це нескінченний дріб у двійковій (аналогічно тому, як 1/3 нескінченний у десятковій). Комп'ютер зберігає лише обмежену кількість бітів мантиси, тому число округлюється до найближчого можливого значення — це округлення й спричиняє видиму "похибку".
Подвійна точність проти одинарної
Double (64 біти) дає більше бітів для мантиси, ніж float (32 біти), а отже, вищу точність — але навіть double не усуває проблему принципово, лише зменшує видимість похибки для більшості практичних розрахунків.
Навіщо це потрібно
- Зрозуміти й діагностувати несподівані похибки округлення у фінансових чи наукових розрахунках.
- Побачити точне двійкове представлення конкретного числа з рухомою комою.
- Пояснити колезі чи студенту, чому порівняння дробових чисел на точну рівність — погана практика.
Субнормальні числа біля нуля
Коли значення числа занадто мале для звичайного представлення (значуще число з розрядом, що починається з неявної одиниці), IEEE 754 переходить у субнормальний (denormalized) режим, де ця неявна одиниця відкидається — це дозволяє представляти ще менші за модулем числа ціною поступової втрати точності замість різкого стрибка до нуля. Такий "плавний" перехід до нуля кращий за раптове обнулення, але субнормальні обчислення на деяких процесорах помітно повільніші за звичайні.