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

Steven D'Aprano steve at pearwood.info
Sat Mar 27 01:05:27 CET 2010


On Fri, 26 Mar 2010 12:19:06 pm P.J. Eby wrote:
> At 11:57 AM 3/26/2010 +1100, Steven D'Aprano wrote:
> >But they're not -- they're *signals* for "your calculation has gone
> >screwy and the result you get is garbage", so to speak. You
> >shouldn't even think of a specific NAN as a piece of specific
> >garbage, but merely a label on the *kind* of garbage you've got (the
> >payload): INF-INF is, in some sense, a different kind of error to
> >log(-1). In the same way you might say "INF-INF could be any number
> >at all, therefore we return NAN", you might say "since INF-INF could
> >be anything, there's no reason to think that INF-INF == INF-INF."
>
> So, are you suggesting that maybe the Pythonic thing to do in that
> case would be to cause any operation on a NAN (including perhaps
> comparison) to fail, rather than allowing garbage to silently
> propagate?

Certainly not. That defeats the whole purpose of NANs. I wish floating 
point calculations in Python would return NANs rather than raise the 
exceptions they do now. I can't speak for others, but in my experience 
NANs are a much nicer way to do maths-related programming. I've 
programmed with a system that supported NANs extensively (Apple's SANE, 
circa 1990), and I miss it so.

Note also that NANs do not necessarily contaminate every expression or 
function call. The standard allows for them to "cancel out", so to 
speak, where it is mathematically justifiable:

>>> nan = float('nan')
>>> 1.0**nan
1.0

so you shouldn't assume that the presence of a NAN in a calculation is 
the kiss of death.


> In other words, if NAN is only a signal that you have garbage, is
> there really any reason to keep it as an *object*, instead of simply
> raising an exception?  Then, you could at least identify what
> calculation created the garbage, instead of it percolating up through
> other calculations.

The standard distinguishes between signalling NANs and quiet NANs (which 
propagate as values). By default, signalling NANs are usually converted 
to quiet NANs, but the caller is supposed to be able to be able to 
change that behaviour to a floating point signal which can be trapped. 
In Python, the equivalent would be an exception.



-- 
Steven D'Aprano


More information about the Python-Dev mailing list