GUIDE 07

Погрешность плавающей запятой: почему 0,1+0,2 и sin(π) выглядят неверно

Почему 0,1+0,2 в двойной точности IEEE 754 даёт 0,30000000000000004, как 12-разрядный вывод показывает 0,3, коррекция sin(π), 170! и переполнение, предел 2⁵³ и катастрофическое сокращение.

Выведите 0.1 + 0.2 в большинстве языков программирования — и получите 0,30000000000000004. Ничего не сломалось: так компьютеры хранят вещественные числа. В этом руководстве объясняется формат двойной точности IEEE 754, который используют SciKey и большинство вычислительных программ, как его ограничения проявляются в результатах и как калькулятор с ними справляется.

1. Двойная точность IEEE 754

Число двойной точности (binary64) занимает 64 бита.

ЧастьБитыНазначение
Знак1Положительное или отрицательное
Порядок11Какая степень двойки
Мантисса52Значащие разряды (фактически 53 со скрытой старшей единицей)

53 значащих бита соответствуют примерно 15–17 десятичным цифрам. Наибольшее представимое значение — около 1,797×10³⁰⁸, а расстояние между 1 и следующим числом двойной точности (машинный эпсилон) равно 2⁻⁵² ≈ 2,22×10⁻¹⁶.

2. У 0,1 нет точного двоичного представления

Как 1/3 = 0,333… никогда не заканчивается в десятичной системе, так и 1/10 не заканчивается в двоичной: 0,1 = 0,0001100110011…₂ — бесконечная периодическая дробь. Она округляется до 53 бит, поэтому на самом деле хранится значение

0,1000000000000000055511151231257827…

0,2 тоже хранится с небольшим избытком. Их сумма переносит обе погрешности и даёт 0,3000000000000000444…, а это другое число двойной точности, чем то, в котором хранится 0,3 (0,2999999999999999888…). Поэтому кратчайшая десятичная запись, однозначно задающая сумму, — 0,30000000000000004.

По той же причине 0.1×3 тоже равно 0,30000000000000004. Десятичные дроби со знаменателями — степенями двойки, такие как 0,5, 0,25 и 0,375, в двоичной системе точны и погрешности не несут.

3. Почему калькулятор всё же показывает 0,3

SciKey выводит не «сырое» внутреннее значение, а округляет его до заданного числа значащих цифр (по умолчанию 12). При округлении до 12 цифр 0,30000000000000004 становится 0,300000000000, то есть 0,3. Погрешность находится в 17-м разряде и до экрана не доходит.

Карманные инженерные калькуляторы работают так же: как правило, они считают примерно с 15 внутренними разрядами и показывают 10, скрывая мельчайшие погрешности на этапе вывода. Меняется только отображение, хранимое значение по-прежнему 0,30000000000000004. При дальнейших вычислениях обычно остаются погрешности порядка 10⁻¹⁶, которые на практике не важны.

4. Почему sin(π) не равен нулю

В режиме RAD sin(π) должен быть ровно 0. Но π иррационально, и ближайшее к π число двойной точности примерно на 1,22×10⁻¹⁶ меньше истинного значения. Вблизи π синус имеет наклон −1, поэтому sin(π в двойной точности) ≈ 1,2246×10⁻¹⁶. Сам синус вычислен точно; просто на входе никогда не было точного π.

SciKey исправляет это по следующим правилам:

  1. В режимах DEG и GRAD аргумент точно приводится по модулю 360° (400 град), а кратные 90° дают точные значения: sin(180) = 0, cos(90) = 0, а tan(90) не определён и поэтому возвращает ошибку.
  2. В режиме RAD, если аргумент совпадает с целым кратным π с относительной погрешностью 10⁻¹³, sin возвращает 0; если совпадает с нечётным кратным π/2, cos возвращает 0, а tan — ошибку.

Поэтому sin(π) в SciKey показывает 0. Коррекция действует только вблизи кратных π и не влияет ни на какие другие вычисления.

5. Большие числа: факториалы и переполнение

Факториалы растут быстро. 170! ≈ 7,25741561531×10³⁰⁶ ещё помещается в число двойной точности, а 171! ≈ 1,24×10³⁰⁹ уже превышает максимум 1,797×10³⁰⁸. Поэтому n! в SciKey принимает целые от 0 до 170, а 171! возвращает ошибку переполнения.

На практике большие факториалы обычно стоят в отношениях. Число сочетаний C(200, 3) равно 200!/(3!·197!), но nCr(200, 3) = 1313400 вычисляет его напрямую, без огромных промежуточных значений. В теории вероятностей также принято брать логарифмы и складывать их.

6. Предел целых чисел: 2⁵³

При 53 значащих битах все целые числа до 2⁵³ = 9007199254740992 представляются точно. Выше числа двойной точности начинают пропускать целые. 2⁵³ + 1 непредставимо и округляется обратно до 2⁵³, поэтому 2^53+1-2^53 даёт 0, а не 1: прибавленная единица исчезла при сохранении суммы.

Поэтому SciKey показывает двоичное, восьмеричное и шестнадцатеричное представления только для целых с модулем до 2⁵³; дальше младшие разряды не гарантированы. По той же причине номера карт или идентификаторы длиннее 16 цифр меняют последние цифры, если обращаться с ними как с числами.

7. Катастрофическое сокращение — самая опасная погрешность

Вычитание двух почти равных чисел уничтожает старшие разряды и оставляет в основном погрешность. Это называется катастрофическим сокращением (потерей значимости).

Пример 1. (1+1E-15)-1 должно давать 10⁻¹⁵, но двойная точность даёт 1,11022302463×10⁻¹⁵. При сохранении 1 + 10⁻¹⁵ возникает ошибка округления порядка 10⁻¹⁶, и после вычитания 1 она составляет 11 % результата.

Пример 2. При x = 10⁸ значение √(x²+1) − x примерно равно 5×10⁻⁹. При прямом вычислении √(10¹⁶+1) неотличимо от 10⁸, и результат равен 0. Умножение на сопряжённое даёт равносильную форму без вычитания:

√(x²+1) − x = 1 / (√(x²+1) + x)

Сохраните 10⁸ в x, и 1/(sqrt(x^2+1)+x) точно вернёт 5×10⁻⁹.

Пример 3. 1 − cos(10⁻⁸) примерно равно 5×10⁻¹⁷, но cos(10⁻⁸) округляется ровно до 1, и прямой результат — 0. С тождеством 1 − cos x = 2 sin²(x/2) выражение 2sin(0.5E-8)^2 даёт 5×10⁻¹⁷ (режим RAD).

Никакое число выводимых цифр этого не исправит. Формулу нужно переписать.

8. Практические советы

  • Не проверяйте точное равенство. Чтобы сравнить два вычисленных результата, проверяйте, достаточно ли мала их разность (например, относительная погрешность 10⁻¹²).
  • Деньги считайте в целых единицах. Работайте в наименьших денежных единицах (например, в копейках) как с целыми числами, чтобы дробные погрешности не накапливались.
  • Избегайте вычитания почти равных чисел. Умножайте на сопряжённое, используйте тождества или преобразуйте выражение, чтобы убрать вычитание.
  • Для больших чисел работайте с отношениями. Когда факториалы или степени «взрываются», используйте nCr, логарифмы или сначала сокращайте.
  • Не округляйте промежуточные результаты. Погрешность двойной точности — около 10⁻¹⁶, а ручное округление до четырёх цифр вносит погрешность порядка 10⁻⁴. Бо́льшие ошибки обычно вносит человек, а не машина.
  • Попробуйте увеличить вывод до 15 цифр. Если результат выглядит странно, покажите больше цифр, чтобы увидеть внутреннее значение и отличить погрешность в последних разрядах от действительно неверной формулы.

→ Открыть калькулятор Справочник функций

Обновлено: 2026-09-24