Steven D'Aprano added the comment:

On 19/08/13 23:15, Oscar Benjamin wrote:

> So with the current implementation I can do:
>
>>>> from decimal import Decimal as D, localcontext, Context, ROUND_DOWN
>>>> data = [D("0.1375"), D("0.2108"), D("0.3061"), D("0.0419")]
>>>> print(statistics.variance(data))
> 0.01252909583333333333333333333
>>>> with localcontext() as ctx:
> ...     ctx.prec = 2
> ...     ctx.rounding = ROUND_DOWN
> ...     print(statistics.variance(data))
> ...
> 0.010
>
> The final result is not accurate to 2 d.p. rounded down. This is
> because the decimal context has affected all intermediate computations
> not just the final result.

Yes. But that's the whole point of setting the context to always round down. If 
summation didn't always round down, it would be a bug.

If you set the precision to a higher value, you can avoid the need for 
compensated summation. I'm not prepared to pick and choose which contexts I'll 
honour. If I honour those with a high precision, I'll honour those with a low 
precision too. I'm not going to check the context, and if it is "too low" 
(according to whom?) set it higher.

>Why would anyone prefer this behaviour over
> an implementation that could compensate for rounding errors and return
> a more accurate result?

Because that's what the Decimal standard requires (as I understand it), and 
besides you might be trying to match calculations on some machine with a lower 
precision, or different rounding modes. Say, a pocket calculator, or a Cray, or 
something. Or demonstrating why rounding matters.

Perhaps it will cause less confusion if I add an example to show a use for 
higher precision as well.

> If statistics.sum and statistics.add_partial are modified in such a
> way that they use the same compensated algorithm for Decimals as they
> would for floats then you can have the following:
>
>>>> statistics.sum([D('-1e50'), D('1'), D('1e50')])
> Decimal('1')

statistics.sum can already do that:

py> with localcontext() as ctx:
...     ctx.prec = 50
...     x = statistics.sum([D('-1e50'), D('1'), D('1e50')])
...
py> x
Decimal('1')

I think the current behaviour is the right thing to do, but I appreciate the 
points you raise. I'd love to hear from someone who understands the Decimal 
module better than I do and can confirm that the current behaviour is in the 
spirit of the Decimal module.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue18606>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to