NaN comparisons - Call For Anecdotes

Chris Angelico rosuav at gmail.com
Tue Jul 8 17:19:57 CEST 2014


On Wed, Jul 9, 2014 at 12:53 AM, Anders J. Munch <2014 at jmunch.dk> wrote:
> In the end I came up with this hack: Every time I struct.unpack'd a
> float, I check if it's a NaN, and if it is, then I replace it with a
> reference to a single, shared, "canonical" NaN. That means that
> container objects that skip __equal__ when comparing an object to
> itself will work -- e.g. hash keys.

Let's take a step back.

No, let's take a step forward.

And let's take a step back again.

(And we're building a military-grade laser!)

Why *should* all NaNs be equal to each other? You said on the other
list that NaN==NaN was equivalent to (2+2)==(1+3), but that assumes
that NaN is a single "thing". It's really describing the whole huge
area of "stuff that just ain't numbers". Imagine if (x + y) wasn't 4,
but was "table". And (a + b) turned out to be "cyan". Does table equal
cyan, just because neither of them is a number? Certainly not. Neither
should (inf - inf) be equal to (inf / inf). Both of those expressions
evaluate to something that can't possibly be a number - it can't be
anywhere on the number line, it can't be anywhere on the complex
plane, it simply isn't a number. And they're not the same non-numeric
"thing".

For hash keys, float object identity will successfully look them up:
>>> d={}
>>> d[float("nan")]=1
>>> d[float("nan")]=2
>>> x=float("nan")
>>> d[x]=3
>>> d[x]
3
>>> d
{nan: 1, nan: 2, nan: 3}

So I'm not sure where the problems come from. You can iterate over a
dict's keys and look things up with them:

>>> for k,v in d.items():
    print(k,v,d[k])
nan 1 1
nan 2 2
nan 3 3

You can do a simple 'is' check as well as your equality check:

if x is y or x == y:
    print("They're the same")

But any time you compare floats for equality, you *already* have to
understand what you're doing (because of rounding and such), so I
don't see why the special case on NaN is significant, unless as
mentioned above, you want all NaNs to be equal, which doesn't make
sense.

ChrisA



More information about the Python-list mailing list