Короткий ответ
Единственного правильного решения нет: можно работать с суммами в минимальных целых единицах (копейках) вместо дробных рублей, использовать тип Decimal для критичных расчётов, либо принять заранее согласованный порог допустимого округления — выбор зависит от требуемой точности сверки и производительности расчётов.
Как это работает подробнее
float64 хранит дробные десятичные числа приближённо в двоичном виде, поэтому последовательное сложение многих денежных значений накапливает мелкие ошибки округления; хранение сумм как целых чисел в минимальных единицах (копейках) полностью устраняет проблему двоичного округления для сложения, а Decimal в Python даёт точную десятичную арифметику ценой меньшей производительности и более сложного кода.
Пример кода
Пример на Python
import pandas as pd
df = pd.DataFrame({'amount_rub': [10.10, 20.20, 30.30]})
df['amount_kopecks'] = (df['amount_rub'] * 100).round().astype('int64')
total_kopecks = df['amount_kopecks'].sum()
total_rub = total_kopecks / 100
print(total_rub)Что использовать на практике
- На практике. если отчёт должен сверяться с бухгалтерией "до копейки", стоит привести входные суммы к целым копейкам сразу при загрузке данных и выполнять все промежуточные расчёты в этих единицах, переводя обратно в рубли только для отображения; если расхождения допустимы в пределах, например, рубля на крупные агрегаты, достаточно явного округления итоговых сумм и сравнения с допустимой погрешностью вместо точного равенства.
- Проверка. сумма, посчитанная через целые копейки и затем переведённая обратно в рубли, должна точно совпадать с ожидаемым контрольным значением 60.60, в отличие от потенциальных микрорасхождений при прямом суммировании дробных float.
Подводные камни
- Частые ошибки. сравнивают суммы, посчитанные в pandas, с суммами из другой системы через точное равенство float без учёта погрешности, делая ложный вывод о "расхождении в данных", хотя разница объясняется исключительно двоичным округлением; переводят всё в Decimal "на всякий случай" даже там, где объём данных и требования к точности этого не оправдывают, сильно замедляя расчёты.