比较“float('nan')”和“math.nan”

问题描述 投票:1回答:4

我有一个浮点变量,可能是也可能不是数字,我想检查是否是这种情况。有了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

python equality
4个回答
2
投票

“不是数字”(在某种意义上)是没有价值的。

传统上,根据IEEE浮点规范,它不等于自身。

那是因为没有有意义的价值可供比较。

事实上,some people use this fact to detect NaN,所以你可以尝试x != x作为你的条件(虽然链接的问答可以说有一些更好的建议)。

但是,表达式math.nan is math.nan是正确的,因为is执行对象身份比较而不是值等价/相等比较。


1
投票

这不是特殊行为:is返回两个对象实际上是指同一个东西(主要是在内存中),而==返回两个对象是否具有相同的值。

为了看他们是否提到相同的东西,我们可以使用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定义为与ab具有相同值的新变量时,它是==,但is返回False

NaNs也是如此。


1
投票

那是因为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定义的一部分,因为它在现代计算机上使用。根据定义,NaN != NaN绝不能与自己相等。它是关于浮点数如何工作的国际标准的一部分,并且这种行为内置于现代CPU中。


0
投票

虽然它们不是同一个对象(因为它们来自不同的模块,它们是单独实现的)并且它们不相等(通过设计math.isnan),但是函数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

虽然它们彼此不相等但并不相同:

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.