mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
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
18 lines
672 B
Python
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)"
|