NaN 很奇怪。
NaN Is Weird

原始链接: https://brassnet.biz/blog/nan-is-weird.html

最近在Python Discord的讨论中,发现`float('nan')`(非数字)存在一种奇怪的行为。令人惊讶的是,`nan`是可哈希的,允许将其添加到集合并用作字典的键。然而,`nan`甚至不等于自身(`nan == nan`的结果是`False`),这意味着每个`nan`实例都被认为是唯一的。 这导致了意想不到的结果:一个集合可以包含多个`nan`值,一个字典可以保存多个以`nan`作为键的条目——但使用`nan`本身检索值会引发`KeyError`。只有使用*特定*的`nan`实例(存储在变量中)才能访问字典。 即使计算可迭代对象中`nan`的出现次数也是不准确的,因为`Counter`将每个`nan`视为不同的值。虽然这在实际应用中没有用处,但这展示了Python处理`nan`值时一个有趣且违反直觉的特性。

## NaN:深入探讨“非数字” 一则Hacker News讨论围绕编程中“NaN”(非数字)的特殊行为。核心问题是:NaN *不* 等于自身,这是IEEE 754浮点标准的结果,而非特定语言的错误。 用户指出这会影响各种功能。C++的`std::sort`在遇到NaN时可能崩溃,而Python对NaN的哈希处理不保证一致性。这源于NaN代表一个无法表示或未定义的值——比较两个“未知”量无法产生明确的“相等”或“不相等”结果。 对话还涉及特定语言的怪癖。Python对除以零的处理(引发异常而不是返回NaN/无穷大)被批评为不一致。Rust通过区分相等性特征来解决这个问题,从而区分具有潜在非自等值的类型,例如NaN。最终,讨论强调NaN是计算机算术中一个基本且奇怪的方面。
相关文章

原文

Published March 02, 2026

Last week in the Python Discord we had an unusual discussion about a Python oddity. Specifically concerning float('nan'). It turns out that (rather unsurprisingly when you think about it) float('nan') is hashable.


>>> hash(float('nan'))
274121555

If it is hashable you can put it in a set:


>>> set(float('nan') for _ in range(10))
{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan}

But why are there 10 copies of nan in that set??? A set shouldn't contain duplicates but that set obviously does. This comes down to the simple fact that no two instances of nan equal one another:


>>> float('nan') == float('nan')
False

In fact, the same nan doesn't even equal itself!


>>> nan = float('nan')
>>> nan == nan
False
>>> nan is nan
True

Just to make life even more fun, you can use nan as a key in a dictionary:


>>> my_dict = {float('nan'): 1, float('nan'): 2}
>>> my_dict
{nan: 1, nan: 2}

But, of course, you can't actually get to those values by their keys:


>>> my_dict[float('nan')]
Traceback (most recent call last):
  File "", line 1, in 
    my_dict[float('nan')]
    ~~~~~~~^^^^^^^^^^^^^^
KeyError: nan

That is, unless you stored the specific instance of nan as a variable:


>>> my_dict[nan] = 3
>>> my_dict[nan]
3

You can always get the keys from the dictionary and work that way, but who knows if you'll get the nan you're looking for:


>>> my_keys = list(my_dict.keys())
>>> my_dict[my_keys[0]]
1

As a bonus, we can't even get an accurate count of how many times nan appears in an iterable...


>>> from collections import Counter
>>> Counter(float('nan') for _ in range(10))
Counter({nan: 1, nan: 1, nan: 1, nan: 1, nan: 1, nan: 1, nan: 1, nan: 1, nan: 1, nan: 1})

While I can't see myself ever, deliberately, using nan as a dictionary key, it is a fun little Python oddity.



联系我们 contact @ memedata.com