[Python-Dev] Mixing float and Decimal -- thread reboot

Raymond Hettinger raymond.hettinger at gmail.com
Sun Mar 21 23:58:14 CET 2010


On Mar 21, 2010, at 3:35 PM, Guido van Rossum wrote:
> 
>> It seems to me that Decimals and floats should be considered at
>> the same level (i.e. both implement Real).
> 
> Agreed, but doesn't help. (Except against the idea that Decimal goes
> on the "integer" side of Fraction, which is just wrong.)

Woohoo!  Glad you agree.
I was concerned that idea
was gathering a following.


> 
>> There is no need to embed a notion of "imperfect answer".
>> Numbers themselves are exact and many mixed operations
>> can be exact if the coercions go the right way.
> 
> Division cannot, in general (I consider floor division a bastard child
> of the integers). And for multiplication it seems that rounding at
> some point becomes necessary since the alternative would be to use
> infinite precision.

Perception here is probably dictated by the use case of the beholder :-)
In the accounting world, such operations are very common (part of
getting three apples for one dollar recorded as 0.33, 0.33, and 0.34
in the individual apple accounts).  Cost allocation tools use floor
division all the time.  Amortization computations always have to 
take into account that real payments and interest charges do not have 
fractional pennies (or sometimes fractional dollars) and have to 
readjust the amortization accordingly (usually with small roundings
to the interest charges and a small adjustment to the final payment).


> Call it by any name you want. We're looking at revising the hash
> function and allowing mixed operations between Decimal and float, with
> signal that warns about these operations. I see two open issues:
> whether mixed Decimal-float operations should return Decimal and
> float, and whether the warning about such operations should be on or
> off by default. My gut tells me that the signal should be off by
> default. My gut doesn't say much about whether the result should be
> float or Decimal, but I want the reasoning to reach a decision to be
> sound.

My vote is for:

    decimal + float --> decimal
   and to emit a warning by default.

Reasoning for coercion to decimal:

1) decimal + float can be done losslessly and meaningfully

2) decimal/float comparisons can give a useful and non-confusing result for:

             1.1 == Decimal('1.1')  

This needs to return False since the two values:

  a) have different hash values (under either proposal) and

  b) are in-fact, not equal

But, if the decimal were coerced to a binary float, the relation would return True:

    >>> float(decimal.Decimal('1.1')) == 1.1
    True

This is bad.


Reasoning for emitting a warning by default:

1) Real actual use cases for mixed decimal / float operations are rare.
2) But accidental mixed decimal / float is an easy mistake to make.
3) Implicit coercion hides the error.
4) A warning flag gives you a chance to catch your error.
5) A warning is educational (it makes sure that you understand
what your program is doing)
6). A warning is easily silenced either through a) the warnings module,
     b) setting a context flag in decimal, or c) by making the coercion explicit
     using Decimal.from_float().


Raymond




   



More information about the Python-Dev mailing list