Files
Jeongseop Lim 0c5e5f68ee Use compensated summation in sum() like CPython (#9237)
CPython keeps a Neumaier compensation term while sum() accumulates an
exact float or complex, and reaches that path from an exact int start
too. RustPython added items one by one, so sum([0.1] * 10) returned
0.9999999999999999 instead of 1.0.

Port the int, float and complex fast paths of builtin_sum_impl, each
falling back to plain addition at the first item it does not handle.

Assisted-by: Claude Code:claude-opus-5-5
2026-10-20 19:52:27 +09:00

18 lines
672 B
Python

import math
from fractions import Fraction
# Float and complex accumulators keep a compensation term, as in CPython 3.14
assert sum([0.1, 0.2, 0.3]) == 0.6
assert sum(b"/%\x97!\x17", 8.962552828027274) == 299.9625528280273
assert sum([0.1, 0.2, 0.3], 0j) == 0.6 + 0j
assert sum([1j, 0.1, 0.2, 0.3]) == 0.6 + 1j
assert sum([0.1j, 0.2j, 0.3j]) == 0.6j
# The first item of another type falls back to plain addition
assert sum([0.5, Fraction(1, 4)]) == 0.75
assert sum([0.5j, Fraction(1, 4)]) == 0.25 + 0.5j
# The compensation never turns an infinite sum into nan or drops a zero's sign
assert sum([math.inf, 1.0]) == math.inf
assert repr(sum([-0.0j], -0.0j)) == "(-0-0j)"