prePEP: Decimal data type
bokr at oz.net
Thu Nov 6 17:27:14 CET 2003
On Thu, 06 Nov 2003 08:22:15 GMT, Alex Martelli <aleax at aleax.it> wrote:
>Tim Peters wrote:
>> You do need to explicitly round (if desired) after * and /. Because of
>> the high value attached to 100% conformance to imposed standards in
>> accounting apps, I think it's a good thing that you're forced to round
>> explicitly when the result of a calculation can't be represented exactly
>> in the mandated format -- those are exactly the places where your app will
>> fail to meet the requirements, so it's good to be aware of them.
>European Union directives (adopted as laws by member states) mandate
>the rounding procedure to be used in computations involving Euros (round
>to closest Eurocent, always round up on half-Eurocent results); they very
>explicitly mention that this may give a 1-Eurocent discrepancy compared
>to "exact" arithmetic, and give examples; they establish that such a 1-cent
>discrepancy that comes from following exactly the prescribed rules is NOT
>legal cause for any lawsuit whatsoever; they earnestly recommend that all
>computing equipment and programs follow these same rules to avoid the huge
>headaches that would result in trying to reconcile accounts otherwise.
>Thus, for most accounting programs intended to run within the EU (not just
>in Euros: these provisions also apply to the other non-Euro currencies, as
>far as EU law is concerned), I do NOT think it would be a good thing for
>the programmer to have to remember to round explicitly -- the legal mandate
>is about rounding rules and it's quite easy to avoid the "fail to meet the
>requirements", as they seem designed to be easy to meet.
I wonder how they deal with compound interest. E.g., may a contract for a loan
express interest as mathematically continuous between payments? In that case
does rounding from mathematically exact values occur only at payment times?
Is the rounding only applied to the payment amount, so that the princal is
decreased by the exact quantized payment, but the balance retains exactness?
Or is requantization of all values mandated at each transaction? Is each step in
a sum a separate transaction? What about the rules for pre-tax-calculation subtotals
vs accumulating actual receipt stated tax amounts? I remember as a kid bugging
store clerks to sell me two candies separately to stay under the minimum taxable
price threshold twice rather than exceed it once and pay the extra penny ;-)
ISTM these things are 'way beyond the concern of a math package per se, yet a math package
that is intended to support programming of a business/rule/law-abiding application
would have to make it easy to express in program source what the unambiguous intent is,
and not have the math be playing unexpected tricks with the values.
IMO to have rounding/precision applied sub-expression by subexpression is a recipe
for unpleasant surprises. It would be like applying snap-to-grid rules in a drawing
package at every internal intermediate math subexpression evaluation step of the
implementation. BTW, does this mean expressions can't be run through optimizers that
might e.g., hoist a subexpression out of a loop and thereby change how many times
a rounding effect happens? What about advice to eager programmers who want to do the same
optimization by hand? Must they be advised? ISTM programmers will not want to face
these issues in internal implementation, and will instead turn up precision to
close-enough-to-exact, and then just round when they print or interact with databases etc.,
ajusting ad hoc to correct infractions of rules revealed in testing. Chances are that's
what they would wind up doing anyway, using step-wise-rounding-enforcing math.
>Whether Decimal itself allows an optional rounding-policy (including of
>course "no rounding" as a possibility) is one issue (I guess that might
>violate some ANSI or IEEE standard...?) but I most surely do want to be
>able to use such policies in whatever arithmetic type underlies Money --
>so I hope Decimal is at least designed so that _subclasses_ can easily
>provide such customized rounding (e.g., feature-testing for a __round__
>specialmethod, not defined in the baseclass Decimal if need be, but
>offering the needed hook for subclasses to add the functionality).
Agreed -- that something is needed to make defining and coding special rules on top
of the math base easy. I was thinking subclassing too. OTOH, casting about
for the meaning of "context" in this PEP context (;-), I think you could also
develop an implementation convention around a separate Context class, that
would provide instances as customized attribute-name-space contexts, using
__[gs]etattr__ overrides and/or properties, maybe with a metaclass to make parameterized
customization easy to write. Using this sort of thing, you could cause property/attribute
retrieval to return rule-enforcing wrapper objects with money quantities inside,
and any statements and math expressions written in terms of those would
be defined by the wrappers, and assignments would be defined by the context object
whose attribute space was being assigned to.
So long as people are willing write stuff like, e.g., e.total and e.tax
for total and tax values they want operated upon subject to, e.g., custom
Euro rules, IWT that could work.
But I think it's hard to anticipate what will work out slick, so some alternative
implementation sketches for a realistic use case would help clarify. Better
to concentrate on powerful orthogonal primitives and test them against a reference
problem than provide too much of what amounts to speculative app macros, IMO.
More information about the Python-list