[Python-Dev] Decimal <-> float comparisons in py3k.

Steven D'Aprano steve at pearwood.info
Thu Mar 18 13:23:18 CET 2010


On Thu, 18 Mar 2010 08:58:25 am Raymond Hettinger wrote:
> On Mar 17, 2010, at 1:59 PM, Steven D'Aprano wrote:
> > On Thu, 18 Mar 2010 07:44:21 am Raymond Hettinger wrote:
> >> The spectrum of options from worst to best is
> >> 1) compare but give the wrong answer
> >> 2) compare but give the right answer
> >> 3) refuse to compare.
> >
> > Why is 3 the best? If there is a right answer to give, surely
> > giving the right answer it is better than not?
>
> From the early days of the decimal module,
> we've thought that mixed float-decimal operations
> are 1) a bit perilous and 2) have few, if any good
> use cases.

When it comes to *arithmetic* operations, I agree. Is there anyone on 
python-dev willing to argue the case for allowing implicit mixed 
float/Decimal arithmetic operations? The arguments in the PEP seem 
pretty convincing to me, and I'm not suggesting we change that.

But comparison operations are different. For starters, you don't need to 
worry about whether to return a float or a Decimal, because you always 
get a bool. In theory, both Decimals and floats are representations of 
the same underlying thing, namely real numbers, and it seems strange to 
me that I can't ask whether two such real numbers are equal just 
because their storage implementation is different.

I can see three reasonable reasons for avoiding mixed comparisons:

(1) To avoid confusing float-naive users (but they're confused by pure 
float comparisons too).

(2) To avoid mixed arithmetic operations (but comparisons aren't 
arithmetic).

(3) If Decimals and floats compare equal, they must hash equal, and 
currently they don't (but Mark Dickinson thinks he has a solution for 
that).



> Accordingly, any mixed operations should be explicit
> rather than implicit:
>
>      Decimal('1.1') + Decimal.from_float(2.2)
>
> is better than:
>
>      Decimal('1.1') + 2.2

Agreed. The user should explicitly choose whether they want a float 
answer or a Decimal answer.


> To help the user avoid confusion, we flag the latter with a
> TypeError: unsupported operand type(s) for +: 'Decimal' and 'float'.
>
> Unfortunately, in Py2.x, implicit mixed comparisons do not
> raise an exception, and instead will silently fail by giving
>
> an incorrect answer:
>     >>> Decimal('1.1') < 2.2
>     False

That is clearly the wrong thing to do. 

Do you envisage any problems from allowing this instead?

>>> Decimal('1.1') < 2.2
True


> IMO, raising the exception is the right thing to do.
> Short of that though, if we're going to give a result,
> it should at least be a correct one.

+1




-- 
Steven D'Aprano


More information about the Python-Dev mailing list