[Python-Dev] Why is nan != nan?

Mark Dickinson dickinsm at gmail.com
Sat Mar 27 13:22:20 CET 2010


On Fri, Mar 26, 2010 at 11:16 PM, Raymond Hettinger
<raymond.hettinger at gmail.com> wrote:
> Of the ideas I've seen in this thread, only two look reasonable:
> * Do nothing.  This is attractive because it doesn't break anything.
> * Have float.__eq__(x, y) return True whenever x and y are
>    the same NaN object.  This is attractive because it is a
>    minimal change that provides a little protection for
>    simple containers.
> I support either of those options.

Yes;  those are the only two options I've seen that seem workable.  Of
the two, I prefer the first (do nothing), but would be content with
second.

I'd be interested to know whether there's any real-life code that's
suffering as a result of nan != nan.  While the nan weirdnesses
certainly exist, I'm having difficulty imagining them turning up in
real code.

Casey Duncan's point that there can't be many good uses for floats as
dict keys or set members is compelling, though there may be
type-agnostic applications that care (e.g., memoizing).  Similarly,
putting floats into a list must be very common, but I'd guess that
checking whether a given float is in a list doesn't happen that often.
 I suspect that (nan+container)-related oddities turn up infrequently
enough to make it not worth fixing.

By the way, for those suggesting that any operation producing a nan
raise an exception instead:  Python's math module actually does go out
of its way to protect naive users from nans.  You can't get a nan out
of any of the math module functions without having put a nan in in the
first place.  Invalid operations like math.sqrt(-1), math.log(-1),
consistently raise ValueError rather than return a nan.  Ideally I'd
like to see this behaviour extended to arithmetic as well, so that
e.g., float('inf')/float('inf') raises instead of producing
float('nan') (and similarly 1e300 * 1e300 raises OverflowError instead
of producing an infinity), but there are backwards compatibility
concerns.  But even then, I'd still want it to be possible to produce
nans deliberately when necessary, e.g., by directly calling
float('nan').

Python also needs to be able to handle floating-point data generated
from other sources;  for this alone it should be at least able to read
and write infinities and nans.

Mark


More information about the Python-Dev mailing list