[Tutor] How to correct decimal addition.

Oscar Benjamin oscar.j.benjamin at gmail.com
Sat Jan 25 23:09:56 CET 2014


On 25 January 2014 21:38, Keith Winston <keithwins at gmail.com> wrote:
>
> Also, just to be clear: I'd suggest floats because decimal requires
> importing a module and using the non-built-in features thereof,

Importing a module is not something to be afraid of. Python comes with
loads of modules especially so you can import them! :P

Also as of CPython 3.3 the decimal module is rewritten in C (which is
what is normally meant by "built-in").

> especially if you're going to do something like
> decimal.getcontext().prec (even that doesn't set precision AFTER the
> decimal point... only total precision). My point being that I don't
> see the value of sending a beginner into that morass.

Maybe it's tricky for a beginner. It is however good advice that you
should not use binary floating point for financial calculations.

> I actually still
> can't find how to force decimal to round to 3 places after the
> decimal...

I find myself using this:

>>> from decimal import Decimal as D
>>> D('0.1234567').quantize(D('1.000'))
Decimal('0.123')

Perhaps it would be better though to point at this:
>>> round(D('0.123456'), 3)
Decimal('0.123')

> (actually, I can't find a single reference to .prec except
> in examples in the standard library doc of decimal
> http://docs.python.org/3.3/library/decimal.html#decimal.getcontext)

.prec is "significant figures" rather than "decimal places" so it's
not what you want here.

> And finally: when I said "watch out for rounding", I meant be prepared
> for it. It is correct that rounding happens (otherwise the Snopes
> Salami scam happens), and I can't imagine that at the level at which
> the OP is working, any subtle control over rounding will be important
> (i.e. ROUNDING_CEILING or any such thing).

Some calculations need rounding in any fixed-width floating point
system. The decimal module let's you go up to 425 million digits
though:
>>> from decimal import MAX_PREC
>>> MAX_PREC
425000000

More importantly it has traps that you can use to catch any example of
inexact computation:

>>> from decimal import localcontext, Inexact
>>> with localcontext() as ctx:
...     ctx.traps[Inexact] = True
...     D(1) / 3
...
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
decimal.Inexact: [<class 'decimal.Inexact'>]

This way you can feel confident that your results are exact or else
you'd have seen an error message.


Oscar


More information about the Tutor mailing list