NaN that is not equal to itself _even if it's the same variable_ is not a Python oddity, it's an IEEE 754 oddity.
> Last week in the Python Discord we had an unusual discussion about a Python oddity.
Oh, I missed it. But yes, this is more to do with NaN than Python.
> But, of course, you can't actually get to those values by their keys: ... That is, unless you stored the specific instance of nan as a variable:
Worth noting that sets work the same way here, although this was glossed over: you can store multiple NaNs in a set, but not the same NaN instance multiple times. Even though it isn't equal to itself, the insertion process (for both dicts and sets) will consider object identity before object equality:
>>> x = float('nan')
>>> {x for _ in range(10)}
{nan}
And, yes, the same is of course true of `collections.Counter`.Fun fact - in C++ std::sort has undefined behavior, and can crash[1], if you try to sort a container with NaNs in it.
[1] https://stackoverflow.com/questions/18291620/why-will-stdsor...
>>> my_dict[nan] = 3
>>> my_dict[nan]
3
Wait, how does that work if nan isn't equal to itself?Reminds me of this classic 4chan thread which started with an absurd-sounding comparison operator and ended with NaN semantic revelations.
...reminds me that object + object is NaN:
> {} + {}
NaN
see https://www.destroyallsoftware.com/talks/watPS: Wait for it ... Watman! =8-)
It would be more satisfying to learn why hash of nan is not guaranteed to be the same. It feels like a bug.
This is also why Rust has separate PartialEq and Eq traits - the latter is only available for types that don't have weird not-self-equal values like floating point NaNs or SQL NULLs. If you lie to Rust and create a wrapper type over f32 or f64 that has Eq, then you'd get unindexable NaN keys that just sit in your hashmap forever.
The real surprise to me is that Python can index NaN keys sometimes, at least by reference to the original NaN. I knew CPython does some Weird Shit with primitive values, so I assume it's because the hashmap is comparing by reference first and then by value.
NaN == NaN is truly a perversion of equality.
It makes little sense that 1/0 is SIGFPE, but log(-5) is NaN in C.
And the same is true for higher level languages, and their error facilities.
What a mess.
NaN is weird? No, NaN is normal*, NaN PAYLOADS are weird: https://anniecherkaev.com/the-secret-life-of-nan
*This is false, NaN is weird, though maybe it needs to be. It is nowhere written arithmetic on computers must be straightforward.
> we had an unusual discussion about a Python oddity
There are so many discussions about "X language is so weird about it handles numbers!" and it's just IEEE 754 floats.