Все статьи

IEEE 754: почему 0.1 + 0.2 не равно 0.3 в коде

Откройте интерпретатор Python и наберите 0.1 + 0.2 — вместо ожидаемого 0.3 он выдаст 0.30000000000000004. Это не баг конкретного языка, а прямое следствие того, как стандарт IEEE 754 представляет дробные числа в двоичной системе — то же самое произойдёт в JavaScript, Java, C# и почти любом другом языке, использующем этот стандарт.

Три части числа с плавающей точкой

Число по IEEE 754 хранится как три компонента: знак (положительное или отрицательное), мантисса (значащие цифры числа) и порядок (степень, на которую сдвигается точка). Это похоже на научную нотацию: 1.5 × 10², только в двоичной системе.

Почему 0.1 нельзя точно представить в двоичной системе

0.1 в десятичной системе — это бесконечная дробь в двоичной (аналогично тому, как 1/3 бесконечна в десятичной). Компьютер хранит лишь ограниченное количество битов мантиссы, поэтому число округляется до ближайшего возможного значения — это округление и вызывает видимую «погрешность».

Почему это опасно в расчётах с деньгами

Если в интернет-магазине сумма корзины считается как последовательное сложение цен в float, после нескольких десятков позиций итог может «уехать» на копейку от ожидаемого — расхождение незаметно в одной операции, но накапливается. Именно поэтому в финансовых расчётах используют целые числа (копейки вместо рублей) или специальные типы вроде decimal, а не float или double напрямую.

Зачем это нужно

  • Понять и диагностировать неожиданные погрешности округления в финансовых или научных расчётах.
  • Увидеть точное двоичное представление конкретного числа с плавающей точкой.
  • Объяснить коллеге или студенту, почему сравнение дробных чисел на точное равенство — плохая практика.

Субнормальные числа рядом с нулём

Когда значение числа слишком мало для обычного представления (значащее число с разрядом, начинающимся с неявной единицы), IEEE 754 переходит в субнормальный (denormalized) режим, где эта неявная единица отбрасывается — это позволяет представлять ещё меньшие по модулю числа ценой постепенной потери точности вместо резкого скачка к нулю. Такой «плавный» переход к нулю лучше внезапного обнуления, но субнормальные вычисления на некоторых процессорах заметно медленнее обычных.

Попробовать инструмент