Why not FP for Money?

Bengt Richter bokr at oz.net
Sat Sep 25 13:54:17 EDT 2004


On Sat, 25 Sep 2004 11:31:53 +0200, aleaxit at yahoo.com (Alex Martelli) wrote:

>Bengt Richter <bokr at oz.net> wrote:
>   ...
>> ISTM maybe decimal _literals_ should be represented internally _exactly_,
>> and exactness be preserved in results of expressions involving only
>> literals with +-*/ operations.
>
>IOW, you think that *decimal _literals_* should actually be *rationals*,
>and this new type 'rational' should be used only internally for
>computation between decimal literals, not otherwise made available to
>the user, e.g. for I/O...?  If we go to the trouble of introducing a
>rational type, why not make it explicitly available to the user then?
>
Interesting question. IWT that exact decimal literals would have a natural
compatibility with a full rational type, just as other exact numerical literals
(e.g. integers and longs) would, but I'm not sure that's enough to call for
an integrated full rational type. (Practicality beats purity?)

A plain decimal literal wouldn't need to be a rational, if you kept a power of
ten exponent instead of a denominator when the value is non-integral. I just bumped
into the need for some rational capability when considering practical use involving
division.

Maybe we could call it an exact decimal type, and let its capability be limited to
+-*/ unless someone wants to subtype and extend it, and just have some caveats re
performance/memory hits if you try to write general polynomial evaluations etc. using it.

This limited type would be explicitly available to the user, and could have an explicit
constructor that could accept other numeric types (including float plus spec of rounding
to create an exact value). (I have a toy that does this much pretty much brute force).

The reason for exactness was to get around the issue of what is specified in the Decimal
"context" (i.e., default number of decimals and rounding mode) before coming into contact
with a Decimal instance that carried a reference to such a context. I suspect anything other
than exact computations between literals would lead to counter-intuitive surprises when
mixed with Decimal instance terms, or else require annoying cruft in "spelling."

Interactively, I would expect exact decimal literals to be assignable and useable in
+-* expressions and return exact decimal literals as their __repr__ values, but the
question remains what repr(1d/3d) should return. I suppose str(1d/3d) could have an
approximate representation. My exactdec toy round-trips eval(repr(x))==x thus:

 >>> from ut.exactdec import ED
 >>> x = ED(1)/ED(3)
 >>> x
 ED('1 / 3')
 >>> eval(repr(x))==x
 True

I guess we would need some kind of '1d/3d' representation (perhaps just that?).
The trouble is that such a representation, while round-trippable, is not always
human-friendly. E.g.,

 >>> ED(1)+ED('2/7')
 ED('9 / 7')

vs e.g. a limited-precision indication of value for the same:

 >>> (ED(1)+ED('2/7')).round(6)
 ED('1.285714')

I guess a str version could have trailing .. to indicate more decimals, e.g.,
    1.285714..

I vary repr with value also, e.g.,
 >>> (ED(1)+ED('2/7'))*ED('1e6')
 ED('9000000 / 7')
 >>> (ED(1)+ED('2/7'))*ED('1e-6')
 ED('0.000009 / 7')
 >>> (ED(1)+ED('2/7'))*ED('1e-26')
 ED('9.0e-26 / 7')

So the concept evolves. Next mutation? ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list