Feature suggestion: sum() ought to use a compensated summation algorithm

Ivan Illarionov ivan.illarionov at gmail.com
Sat May 3 21:20:29 EDT 2008


On Sat, 03 May 2008 17:43:57 -0700, George Sakkis wrote:

> On May 3, 7:12 pm, Ivan Illarionov <ivan.illario... at gmail.com> wrote:
>> On Sun, 04 May 2008 00:31:01 +0200, Thomas Dybdahl Ahle wrote:
>> > On Sat, 2008-05-03 at 21:37 +0000, Ivan Illarionov wrote:
>> >> On Sat, 03 May 2008 20:44:19 +0200, Szabolcs Horvát wrote:
>>
>> >> > Arnaud Delobelle wrote:
>>
>> >> >> sum() works for any sequence of objects with an __add__ method,
>> >> >> not just floats!  Your algorithm is specific to floats.
>>
>> >> > This occurred to me also, but then I tried
>>
>> >> > sum(['abc', 'efg'], '')
>>
>> >> Interesting, I always thought that sum is like shortcut of
>> >> reduce(operator.add, ...), but I was mistaken.
>>
>> >> reduce() is more forgiving:
>> >> reduce(operator.add, ['abc', 'efg'], '' ) # it works 'abcefg'
>> > Hm, it works for lists:
>> > sum(([1], [2]), [])
>> > [1, 2]
> 
> So it's not reduce() that is more forgiving, it's sum() that makes an
> exception for strings only.
> 
> 
>> > However I find the seccond argument hack ugly. Does the sum way have
>> > any performance advantages over the reduce way?
>>
>> Yes, sum() is faster:
>>
>> $ python -m timeit "" "sum([[1], [2], [3, 4]], [])" 100000 loops, best
>> of 3: 6.16 usec per loop
>>
>> $ python -m timeit "import operator" \ "reduce(operator.add, [[1], [2],
>> [3, 4]])" 100000 loops, best of 3: 11.9 usec per loop
> 
> Not really; you measure the import and the attribute access time in the
> second case. sum() is 2x faster for adding numbers only:
> 
> # Adding integers
> python -mtimeit --setup="x=[1]*100" "sum(x)" 100000 loops, best of 3:
> 4.87 usec per loop python -mtimeit --setup="from operator import add;
> x=[1]*100" "reduce(add,x)"
> 100000 loops, best of 3: 10.1 usec per loop
> 
> # Adding floats
> python -mtimeit --setup="x=[1.0]*100" "sum(x)" 100000 loops, best of 3:
> 5.14 usec per loop python -mtimeit --setup="from operator import add;
> x=[1.0]*100" "reduce(add,x)"
> 100000 loops, best of 3: 10.1 usec per loop
> 
> # Adding tuples
> python -mtimeit --setup="x=[(1,)]*100" "sum(x,())" 10000 loops, best of
> 3: 61.6 usec per loop python -mtimeit --setup="from operator import add;
> x=[(1,)]*100" "reduce(add,x,())"
> 10000 loops, best of 3: 66.3 usec per loop
> 
> # Adding lists
> python -mtimeit --setup="x=[[1]]*100" "sum(x,[])" 10000 loops, best of
> 3: 79.9 usec per loop python -mtimeit --setup="from operator import add;
> x=[[1]]*100" "reduce(add,x,[])"
> 10000 loops, best of 3: 84.3 usec per loop
> 
> George

Thanks for correction. Forget about --setup.

-- 
Ivan



More information about the Python-list mailing list