Короткий ответ
float64 хранит числа в двоичном формате с конечной точностью, поэтому суммирование большого количества денежных значений может давать крошечные расхождения (например, 0.1 + 0.2 ≠ 0.3 точно), которые накапливаются при множестве операций и могут привести к заметным отклонениям в финансовой отчётности.
Как это работает подробнее
десятичные дробные числа вроде 0.1 не имеют точного представления в двоичной системе, поэтому при хранении в float64 они округляются до ближайшего представимого значения; при суммировании миллионов таких значений ошибки округления накапливаются, и итоговая сумма может немного отличаться от "точной" математической суммы.
Пример кода
Пример на Python
import pandas as pd
amounts = pd.Series([0.1] * 1000000)
total = amounts.sum()
print(total)
print(total == 100000.0)Что использовать на практике
- На практике. для большинства аналитических отчётов такая погрешность пренебрежимо мала и не влияет на выводы, но для финансовой отчётности, где суммы должны сверяться до копейки с бухгалтерскими системами, стоит либо работать в минимальных неделимых единицах (копейки/центы как целые числа), либо использовать Decimal для критичных расчётов, либо аккуратно округлять результат перед сравнением и выводом.
- Проверка. total может оказаться не точно равным 100000.0 из-за накопленной погрешности округления float64, что видно при точном сравнении через == и требует использования допустимой погрешности при сверке сумм.
Подводные камни
- Частые ошибки. сравнивают два float на точное равенство (sum1 == sum2) вместо сравнения с допустимой погрешностью (abs(sum1 - sum2) < epsilon), получая ложные "несовпадения" из-за микроскопических ошибок округления; смешивают денежные суммы в разных единицах (рубли и копейки) без явного приведения, что усиливает видимые расхождения при округлении.