[Python-Dev] decimal.py: == and != comparisons involving NaNs

Mark Dickinson dickinsm at gmail.com
Mon Nov 9 14:01:10 CET 2009


On Sun, Nov 8, 2009 at 4:26 PM, Stefan Krah <stefan-usenet at bytereef.org> wrote:
> Hi,
>
> in a (misguided) bugreport (http://bugs.python.org/issue7279) I was
> questioning the reasons for allowing NaN comparisons with == and !=
> rather than raising InvalidOperation.

Some quick recent history:

For reference, the current behaviour dates from r60630.  Before this,
comparisons involving nans behaved even less coherently.  See

http://bugs.python.org/issue1979

for details.

Apart from Python's use of __eq__, the other motivation for the
current behaviour comes from the IEEE 854 standard;  given the
absence of helpful information in the Decimal standard, IEEE 854
is an obvious next place to look.  There's an unofficial copy of the
standard available at:

http://754r.ucbtest.org/standards/854.pdf

Section 5.7 describes twenty-six(!) distinct comparison operators.
So it's not immediately clear which of those twenty-six comparison
operators each of Python's six comparison operators should map
to.  However, in the standard, the first six operations in the table
are somewhat distinguished:  they're the ones that are marked
as corresponding to the usual mathematical operations, and to
Fortran's usual comparison operators (.EQ., etc.).  Given this,
and given that this behaviour seemed to fit well with Python's
needs for __eq__, it seemed to make sense at the time to
map Python's six operators to the first 6 operators in table 3.

> I think two main issues emerge from the brief discussion:
>
> 1. Should the comparison operators follow the 'compare' function
>   from the standard?

That's a possibility.  But see below.

> 2. What is the use of == and != outside the decimal scope?
>
> Mark mentions that Python uses == to test for set and dict memberships,
> but that you cannot put decimal NaNs into sets:
>
> 'TypeError: Cannot hash a NaN value'
>
>
> I want to add that Decimal('NaN') == Decimal('NaN') gives False, which
> should somewhat limit the uses of == for NaNs outside the decimal realm
> anyway.
>
>
> Are there cases where == and != are actually needed to give a result
> for NaNs?

Well, when running in some form of 'non-stop' mode, where (quiet) NaN
results are supposed to be propagated to the end of a computation, you
certainly want equality comparisons with nan just to silently return false.
E.g., in code like:

if x == 0:
    <deal with zero special case>
else:
    <usual algorithm>

nans should just end up in the second branch, without the programmer
having had to think about it too hard.

So I think comparisons with nans should always return either True
or False when InvalidOperation is not trapped. The question is whether
comparisons should always signal when InvalidOperation is trapped
(which is what happens with the default context).

I'm -0.5 on changing the current behaviour:  it may not be exactly right,
and if I were implementing Decimal from scratch I might well do things
differently, but I don't think it's terribly wrong either.  While not based
on the Decimal standard itself, it's based on the next most closely-
related standard.  It works with Python's needs for __eq__ and __ne__.
And it's already out there in Python 2.6;  making minute adjustments
to existing behaviour without a good reason seems like asking for trouble.

Mark


More information about the Python-Dev mailing list