все Python 3mathпонятие
math.fsum
агрегация
Точная сумма чисел с плавающей точкой (без ошибок округления).
Синтаксис
math.fsum(iterable)
Встроенный sum() с Python 3.12 складывает float с компенсацией ошибки и точнее наивного сложения, но точным не является, а fsum() держит набор частичных сумм и округляет один раз в самом конце — разница вылезает на слагаемых очень разного порядка. Платить приходится скоростью: fsum() заметно медленнее и всегда возвращает float, даже если на входе целые. Для денег это не лекарство — там нужен decimal.Decimal, а не fsum().
Примеры
import math
# Классическая иллюстрация «sum накапливает ошибку» с Python 3.12 больше НЕ
# работает: встроенная sum() для float считает компенсированной суммой
# (алгоритм Нейманна), поэтому оба ответа точны.
print(sum([0.1] * 10)) # → 1.0
print(math.fsum([0.1] * 10)) # → 1.0
print(sum([0.1, 0.2, 0.3])) # → 0.6
print(math.fsum([0.1, 0.2, 0.3])) # → 0.6
import math
# Разница между sum и fsum зависит от версии: компенсация во встроенной sum
# крепнет от релиза к релизу. Этот случай на 3.12/3.13 даёт 0.0, на 3.14 — 1.0,
print(sum([1e100, 1, -1e100])) # → ? (0.0 на 3.12/3.13, 1.0 на 3.14)
print(math.fsum([1e100, 1, -1e100])) # → 1.0 (fsum считает точно)
# поэтому ожидание помечено средозависимым. А fsum точен на любой версии:
print(sum([1, 1e100, -1e100, 1])) # → 1.0 (порядок слагаемых меняет ответ)
import math
# Устойчивая иллюстрация: здесь sum теряет единицу на ВСЕХ версиях, fsum — нет.
print(math.fsum([1, 1e100, -1e100, 1])) # → 2.0
См. также
Открыть в полном глоссарииdocs.python.orgСообщить о неточности