Python Glossary English

все 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Сообщить о неточности