[Python-Dev] Re: Decimal data type issues

Tim Peters tim.one at comcast.net
Tue Apr 20 23:11:13 EDT 2004


[Paul Moore]
> ... and I discovered that I understand Decimal far less than I thought
> I did. But after some experimentation, and reading of the spec, I
> think that I've hit on a key point:
>
>     The internal representation of a Decimal instance, and
>     specifically the number of digits of precision stored internally,
>     has no impact on anything, *except when the instance is converted
>     to a string*
>
> The reason for this is that every possible operation on a Decimal
> instance uses context, with the sole exception of the "convert to
> string" operations (sections 4 and 5 of the spec).
>
> As a result of this, I'm not sure that it's valid to care about the
> internal representation of a Decimal instance.

It's not quite right.  While this is a floating-point arithmetic, it was
designed to "preserve scale" so long as precision isn't exceeded.  Because
you can set precision to anything, this is more powerful than it sounds at
first.  For example, Decimal("20.32") - Decimal("8.02") is displayed as
Decimal("12.30").  That final trailing zero is effectively inherited from
"the scales" of the inputs, and is entirely thanks to that the internal
arithmetic is unnormalized.  More info can be found here:

    http://www2.hursley.ibm.com/decimal/IEEE-cowlishaw-arith16.pdf

    However, if unnormalized floating-point is used with
    sufficient precision to ensure that rounding does not
    occur during simple calculations, then exact scale-preserving
    (type-preserving) arithmetic is possible, and the performance
    and other overheads of normalization are avoided.

and in Cowlishaw's FAQ:

    http://www2.hursley.ibm.com/decimal/decifaq4.html#unnari

    Why is decimal arithmetic unnormalized?
 
> ...
> I've avoided considering scale too much here - Decimal has no concept
> of scale, only precision.

As above, it was carefully designed to *support* apps that need to preserve
scale, but as a property that falls out of a more powerful and more general
arithmetic.

Note that the idea that various legacy apps *agree* on what "preserve scale"
means to begin with is silly -- there's a large variety of mutually
incompatible rules in use (e.g., for multiplication there's at least "the
scale of the result is the sum of the scales of the multiplicands", "is the
larger of the multiplicands' scales", "is the smaller of the multiplicands'
scales", and "is a fixed value independent of the multiplicands' scales").
Decimal provides a single arithmetic capable of emulating all those (and
more), but it's up to the app to use enough precision to begin with, and
rescale according its own bizarre rules.

> But that's effectively just a matter of multiplying by the
> appropriate power of 10, so shouldn't be a major issue.

It can also require rounding, so it's not wholly trivial.  For example,
what's 2.5 * 2.5?  Under the "larger (or smaller) input scale" rules, it's
6.2 under "banker's rounding" or 6.3 under "European, and American tax
rounding" rules.  Decimal won't give either of those directly (unless
precision is set to the ridiculously low 2), but it's easy to get either of
them *using* Decimal (or to get 6.25 directly, which is the least surprising
result to people).





More information about the Python-Dev mailing list