prePEP: Money data type

Alex Martelli aleaxit at yahoo.com
Sun Oct 19 04:24:31 EDT 2003


Ian Bicking wrote:
   ...
>> So you think y=x/2 should not work when x is an instance of Money,
>> nor should y=x*z when x is an instance of Money and z is e.g. 0.5?
>> That seems pretty limiting to me.
> 
> I could go either way.  Or rather I'd like both.  If I was doing
> serious accounting programming I *absolutely* would want money*0.5 to
> raise an exception -- I would want to be very explicit about anything
> that had the potential of being imprecise.  It would simply be too easy
> to mess this up otherwise.

There is no "potential of being imprecise" when I divide a money amount
by two: it just may need rounding according to the applicable rules if it
happens to result in a half cent (or whatever other least significant unit).
If, as you suggest and opposite to the ideas from the Fowler article you 
quote, Money instances DON'T carry information about the rules of rounding, 
then it's that lack of information which may create problems.

Note that "potential of being imprecise" (by one cent, and as long as
the EU rules are respected) is specifically allowed in EU regulations,
and they also recommend the 1-cent tolerance be built into data
processing equipment and programs.  I.e., they specifically state that
such 1-cent discrepancy is NOT legal grounds for dispute, as long as
it follows from computations respecting The Rules; and recommend
that accounting programs accept that automatically, pointing out that
reconciliation of accounts would otherwise be cumbersome.  Apparently
that's one more difference between European and American approaches
to accounting arithmetic?

So, in your vision of serious accounting, if I needed to multiply a Euro
amount by 1936.27 (or any of the many other legally mandated rates)
I could not just multiply by 193627 then divide by 100?  Would there
have to be a "precise decimal" type _in addition_ to the Money type to
allow such computations?  (Multiplying money by money seems to make
no dimensional sense -- those rates are dimensionally just numbers,
unless perhaps one's "Money" includes currency denomination, in which
case they can dimensionally be "ratios of currencies").  But these
computations would need rounding rules too; and sticking the rules
with the "precise decimal" when obviously they depend not on the
number, but on the kind of Money (is it European, American, ...?),
seems truly weird to me.

I shudder to think of doing e.g. present value computations on a cash flow, 
let alone seriously complicated arithmetic, in a system where I can't just
use normal arithmetic operations.  Having to boilerplately call
    x.divide_by(y, money.rounding_european)
each and every time I mean
    x/y
BECAUSE for reasons totally unclear to me x isn't allowed to carry
the rounding spec, even though all computations on x must use that
spec, would drive me away in no time.


> If I was a more casual user of Money (which is actually all that I'm
> likely to ever be) then I would be annoyed by that preciseness.
> 
> In this circumstance, it would be reasonable for me to make my own
> money subclass to use in my application, if I wanted to avoid rounding
> errors.  Or, if an option were available for forcing explicit rounding,
> that would also work.  (But in most cases I wouldn't suggest
> subclassing as a feasible means of customization, e.g., for defining a
> standard rounding method -- subclassing for customization sucks)

If you have to customize, subclassing is a decent way to do so.  But
I don't see the need to customize, and thus to subclass, here, when 
we know in advance that most every computation with money will need
to be able to perform rounding according to certain rules.  Sure, ALLOW
customization by subclassing for potential need for "super-weird" rules --
expose the .round method that is internally called to do rounding that
depends on the rules, and if I have to follow ones outside the small set
that we can predict in advance, then the requirement to subclass is not
too onerous.  But normal cases should be in the Money class!


>>> No, the only places where repr() round trips is for Python literals.
>>
>> Not true:
   ...
> Okay, what I said was not entirely true.  I was just concerned that the
> repr() of a money object *must* be readable -- sacrificing readability
> for accurate round-tripping is not acceptable.  It seemed like John was
> suggesting that.  repr() should not take the place of pickle.dumps()

Guaranteed readability is the business of str().  repr() must be complete
and accurate even if that sacrifices readability.  Round-tripping cannot
generally be guaranteed for many types, but when it can it's a sensible
way to double check on completeness and accuracy; readability must
not be allowed to interfere with completeness and accuracy.  Sure, pickle
is there for those times where round-tripping is too onerous on other
grounds, but readability is not one of those grounds -- otherwise what
do you think str() is there FOR?


Alex





More information about the Python-list mailing list