[Python-ideas] Yet another sum function (fractions.sum)

Oscar Benjamin oscar.j.benjamin at gmail.com
Wed Aug 21 13:27:58 CEST 2013


On 21 August 2013 07:25, Peter Otten <__peter__ at web.de> wrote:
> Oscar Benjamin wrote:
>
>> On 19 August 2013 11:09, Peter Otten
>> <__peter__ at web.de> wrote:
>
>>> sum(items, 0.0) would then automatically profit from the clever
>>> optimizations of math.fsum() etc.
>>
>> fsum() is about controlling accumulated rounding errors rather than
>> optimisation (although it may be faster I've never needed to check).
>
> Is I understand it, you can "optimize" for precision, memory usage, code
> simplicity -- not just speed.

Sorry, you're right.

>> Do you think that any of these things should also be changed so that
>> there can be e.g. one sqrt() function that does the right thing for
>> all types?
>
> At the time I only thought about sum(), but yes, for every operation that
> has one "best" implementation per class there should be a uniform way to
> make these implementations available.
[snip]
>
> Classmethods would be yet another option
>
> float.sum(numbers)
>
> or
>
> complex.sqrt(a)
>
> don't look bad, though I'm not sure what the right approach for int.sqrt()
> would be...

It's not necessarily per-class. For sqrt we can write functions
targeted at the Rational ABC that will work for anything that fits
with that part of the numeric tower (including int) e.g.:

import math

def sqrt_ceil(y):
    xguess = int(math.floor(math.sqrt(y)))
    while xguess ** 2 < y: # This can be improved
        xguess += 1
    return xguess

def sqrt_floor(y):
    x = sqrt_ceil(y)
    if x ** 2 != y:
        x -= 1
    return x

def sqrt_exact(y):
    if y.denominator != 1:
        return type(y)(sqrt_exact(y.numerator), sqrt_exact(y.denominator))
    x = sqrt_ceil(y)
    if x ** 2 == y:
        return x
    else:
        raise ValueError('No exact rational root')

I think it's reasonable to have things like that in the fractions
module since that's where the stdlib implements its concrete Rational
type.

A similar thing is possible with fsum. Alternative algorithms can
achieve the same effect for arbitrary radix (e.g. decimal) numeric
types under the appropriate rounding modes so it would be possible to
make it do the right thing for decimals while keeping a fast-path for
sum. This would lead to a significant performance regression for
anyone who was actually hoping that their decimals would get coerced
to floats though. So maybe a function in the decimal module could
provide the fully general algorithm that works well for sensibly
rounded instances of the Real ABC.


Oscar


More information about the Python-ideas mailing list