比较 "float('nan')" 和 "math.nan"
Comparing "float('nan')" and "math.nan"
我有一个浮点变量,它可能是也可能不是数字,我想检查一下是否是这种情况。使用 x = float('nan')
,我观察到一些令我吃惊的行为:
print(x is math.nan)
>>> False
这意味着float('nan')
和math.nan
是不同的对象,这是我没想到的,不过没关系。但是,当我检查 ==
:
是否相等时,结果是一样的
print(x == math.nan):
>>> False
如果我使用 math.isnan(x)
,我会得到所有类型的非数字的正确结果。尽管如此,为什么 float('nan') == math.nan
不计算为 True
?
"Not a number" 是(在某种意义上)没有值。
传统上,根据 IEEE 浮点规范,它不等于自身。
那是因为没有有意义的值可以比较。
事实上,some people use this fact to detect NaN,所以你可以尝试 x != x
作为你的条件(尽管链接的问答可以说有一些更好的建议)。
表达式 math.nan is math.nan
是正确的,因为 is
进行对象标识比较而不是值 equivalence/equality 比较。
这不是特殊行为:is
returns 两个对象是否实际上指的是同一事物(基本上在内存中)并且 ==
returns 两个对象是否具有相同的值。
要查看它们是否指代同一事物,我们可以使用 id()
.
>>> a = [1,2,3]
>>> b = a
>>> id(a)
140302781856200
>>> id(b)
140302781856200
>>> a == b
True
>>> a is b
True
>>> c = [1,2,3]
>>> id(c)
140302781864904
>>> a == c
True
>>> a is c
False
这里我们看到,通过分配 b = a
,它们现在引用同一个列表:因此 is
和 ==
是 True
。但是当我们定义c
为一个新变量,与a
和b
具有相同的值时,它是==
,但是is
returns False
.
NaN
s也是如此。
那是因为 NaN
只是一个浮点值。使用 is
不检查变量是否具有相同的值,它检查它们是否是同一个对象。如果你创建两个具有相同值的浮点数,它们不是同一个对象,它们是两个具有相同值的对象。以此为例:
>>> a = float('nan')
>>> b = float('nan')
>>> a is b
False
因此,即使您以相同的方式创建两个 NaN
值,它们也不是同一个对象。即使对于更琐碎的浮点数也是如此。试试这个:
>>> a = 1.
>>> b = 1.
>>> a is b
False
Python 的默认版本重复使用 一些 值,因此该值的任何实例都是同一个对象。所以以此为例(注意缺少小数,这些是整数而不是浮点数):
>>> a = 1
>>> b = 1
>>> a is b
True
但这是您永远不应依赖的实施细节,它随时可能更改,并且可能因 python 实施而异。但即使如此,NaN
也不是默认 Python 解释器执行此操作的值之一。
您可以使用 id
函数手动检查两个变量是否是同一个对象,该函数为每个同时存在的对象提供一个唯一的编号(尽管删除变量后可以重新使用这些编号,甚至自动)。
>>> a=1.
>>> b=1.
>>> c=float('nan')
>>> d=float('nan')
>>> e=1
>>> f=1
>>> id(a)
139622774035752
>>> id(b)
139622774035872
>>> id(c)
139622774035824
>>> id(d)
139622774035800
>>> id(e)
139622781650528
>>> id(f)
139622781650528
至于为什么它们不相等,这只是现代计算机上使用的 NaN 定义的一部分。根据定义,NaN
绝不能等于其自身。它是关于浮点数如何工作的国际标准的一部分,并且这种行为内置于现代 CPU 中。
虽然它们不是同一个对象(因为它们来自不同的模块,它们分别实现)并且它们不相等(设计 NaN != NaN
),但函数 math.isnan
(and numpy.isnan
如果你想要一个矢量化版本)正是为了这个目的:
import math
import numpy
math.isnan(math.nan)
# True
math.isnan(numpy.nan)
# True
math.isnan(float("nan"))
# True
尽管它们彼此不相等且不相同:
math.nan == numpy.nan or math.nan is numpy.nan
# False
math.nan == float("nan") or math.nan is float("nan")
# False
numpy.nan == float("nan") or numpy.nan is float("nan")
# False
您可以使用“float”中内置的“hex”函数
float('nan') == math.nan # FALSE
float('nan').hex() == math.nan.hex() # TRUE
float('nan').hex() == float('nan').hex() # TRUE
float('nan').hex() == numpy.nan.hex() # TRUE
如果您在 pandas 中使用查询,这将非常有用。我最近尝试使用:
df.eval('A == "NaN"')
应该检查 A 列是否为 NaN。但是,pandas 会自动将字符串“NaN”转换为浮点数。大多数人会推荐使用 df['A'].isna(),但在我们的例子中,尝试将表达式传递到方法中,因此它应该处理任何表达式。
解决方案是:
df.applymap(lambda x: 'NaN' if x.hex() == float('NaN').hex() else x).eval('A == "NaN"')
您可以将 nan 值转换为字符串进行比较。
像这样的东西:
x=float("nan")
s_nan = str(x)
if s_nan == "nan":
# What you need to do...
print('x is not a number')
我有一个浮点变量,它可能是也可能不是数字,我想检查一下是否是这种情况。使用 x = float('nan')
,我观察到一些令我吃惊的行为:
print(x is math.nan)
>>> False
这意味着float('nan')
和math.nan
是不同的对象,这是我没想到的,不过没关系。但是,当我检查 ==
:
print(x == math.nan):
>>> False
如果我使用 math.isnan(x)
,我会得到所有类型的非数字的正确结果。尽管如此,为什么 float('nan') == math.nan
不计算为 True
?
"Not a number" 是(在某种意义上)没有值。
传统上,根据 IEEE 浮点规范,它不等于自身。
那是因为没有有意义的值可以比较。
事实上,some people use this fact to detect NaN,所以你可以尝试 x != x
作为你的条件(尽管链接的问答可以说有一些更好的建议)。
表达式 math.nan is math.nan
是正确的,因为 is
进行对象标识比较而不是值 equivalence/equality 比较。
这不是特殊行为:is
returns 两个对象是否实际上指的是同一事物(基本上在内存中)并且 ==
returns 两个对象是否具有相同的值。
要查看它们是否指代同一事物,我们可以使用 id()
.
>>> a = [1,2,3]
>>> b = a
>>> id(a)
140302781856200
>>> id(b)
140302781856200
>>> a == b
True
>>> a is b
True
>>> c = [1,2,3]
>>> id(c)
140302781864904
>>> a == c
True
>>> a is c
False
这里我们看到,通过分配 b = a
,它们现在引用同一个列表:因此 is
和 ==
是 True
。但是当我们定义c
为一个新变量,与a
和b
具有相同的值时,它是==
,但是is
returns False
.
NaN
s也是如此。
那是因为 NaN
只是一个浮点值。使用 is
不检查变量是否具有相同的值,它检查它们是否是同一个对象。如果你创建两个具有相同值的浮点数,它们不是同一个对象,它们是两个具有相同值的对象。以此为例:
>>> a = float('nan')
>>> b = float('nan')
>>> a is b
False
因此,即使您以相同的方式创建两个 NaN
值,它们也不是同一个对象。即使对于更琐碎的浮点数也是如此。试试这个:
>>> a = 1.
>>> b = 1.
>>> a is b
False
Python 的默认版本重复使用 一些 值,因此该值的任何实例都是同一个对象。所以以此为例(注意缺少小数,这些是整数而不是浮点数):
>>> a = 1
>>> b = 1
>>> a is b
True
但这是您永远不应依赖的实施细节,它随时可能更改,并且可能因 python 实施而异。但即使如此,NaN
也不是默认 Python 解释器执行此操作的值之一。
您可以使用 id
函数手动检查两个变量是否是同一个对象,该函数为每个同时存在的对象提供一个唯一的编号(尽管删除变量后可以重新使用这些编号,甚至自动)。
>>> a=1.
>>> b=1.
>>> c=float('nan')
>>> d=float('nan')
>>> e=1
>>> f=1
>>> id(a)
139622774035752
>>> id(b)
139622774035872
>>> id(c)
139622774035824
>>> id(d)
139622774035800
>>> id(e)
139622781650528
>>> id(f)
139622781650528
至于为什么它们不相等,这只是现代计算机上使用的 NaN 定义的一部分。根据定义,NaN
绝不能等于其自身。它是关于浮点数如何工作的国际标准的一部分,并且这种行为内置于现代 CPU 中。
虽然它们不是同一个对象(因为它们来自不同的模块,它们分别实现)并且它们不相等(设计 NaN != NaN
),但函数 math.isnan
(and numpy.isnan
如果你想要一个矢量化版本)正是为了这个目的:
import math
import numpy
math.isnan(math.nan)
# True
math.isnan(numpy.nan)
# True
math.isnan(float("nan"))
# True
尽管它们彼此不相等且不相同:
math.nan == numpy.nan or math.nan is numpy.nan
# False
math.nan == float("nan") or math.nan is float("nan")
# False
numpy.nan == float("nan") or numpy.nan is float("nan")
# False
您可以使用“float”中内置的“hex”函数
float('nan') == math.nan # FALSE
float('nan').hex() == math.nan.hex() # TRUE
float('nan').hex() == float('nan').hex() # TRUE
float('nan').hex() == numpy.nan.hex() # TRUE
如果您在 pandas 中使用查询,这将非常有用。我最近尝试使用:
df.eval('A == "NaN"')
应该检查 A 列是否为 NaN。但是,pandas 会自动将字符串“NaN”转换为浮点数。大多数人会推荐使用 df['A'].isna(),但在我们的例子中,尝试将表达式传递到方法中,因此它应该处理任何表达式。 解决方案是:
df.applymap(lambda x: 'NaN' if x.hex() == float('NaN').hex() else x).eval('A == "NaN"')
您可以将 nan 值转换为字符串进行比较。 像这样的东西:
x=float("nan")
s_nan = str(x)
if s_nan == "nan":
# What you need to do...
print('x is not a number')