在没有numpy的python中分配一个变量NaN
Posted
技术标签:
【中文标题】在没有numpy的python中分配一个变量NaN【英文标题】:Assigning a variable NaN in python without numpy 【发布时间】:2013-10-22 20:18:23 【问题描述】:大多数语言都有一个 NaN 常量,您可以使用它来为变量分配值 NaN。 python可以不使用numpy做到这一点吗?
【问题讨论】:
C、C++、java、C#、ocaml,它是很多语言的一部分。 NaN,在 C 中是NAN
;从 C99 开始,它是在 math.h
中定义的常量。 (我觉得将该语言的最新标准化版本称为该语言是公平的。因此“C”是 C11。)(参见***.com/questions/1923837/how-to-use-nan-and-inf-in-c);在 C++ 中,它也是 NAN
,还有 nan()
、nanf()
和 nanl()
,尽管我不太确定它们的作用。 double.NaN
在 Java 中,Double.NaN
在 C# 中......
【参考方案1】:
是的——使用math.nan
。
>>> from math import nan
>>> print(nan)
nan
>>> print(nan + 2)
nan
>>> nan == nan
False
>>> import math
>>> math.isnan(nan)
True
在 Python 3.5 之前,可以使用 float("nan")
(不区分大小写)。
请注意,检查是否为 NaN 的两个事物是否彼此相等将始终返回 false。这部分是因为“不是数字”的两件事不能(严格来说)说彼此相等——有关更多详细信息和信息,请参阅What is the rationale for all comparisons returning false for IEEE754 NaN values?。
如果您需要确定某个值是否为 NaN,请改用 math.isnan(...)
。
此外,在尝试将 NaN 存储在 list
或 dict
等容器类型中(或使用自定义容器类型时)时,==
对 NaN 值的操作的确切语义可能会导致微妙的问题。详情请见Checking for NaN presence in a container。
您还可以使用 Python 的 decimal 模块构造 NaN 数:
>>> from decimal import Decimal
>>> b = Decimal('nan')
>>> print(b)
NaN
>>> print(repr(b))
Decimal('NaN')
>>>
>>> Decimal(float('nan'))
Decimal('NaN')
>>>
>>> import math
>>> math.isnan(b)
True
math.isnan(...)
也适用于 Decimal 对象。
但是,您不能在 Python 的 fractions 模块中构造 NaN 数:
>>> from fractions import Fraction
>>> Fraction('nan')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python35\lib\fractions.py", line 146, in __new__
numerator)
ValueError: Invalid literal for Fraction: 'nan'
>>>
>>> Fraction(float('nan'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python35\lib\fractions.py", line 130, in __new__
value = Fraction.from_float(numerator)
File "C:\Python35\lib\fractions.py", line 214, in from_float
raise ValueError("Cannot convert %r to %s." % (f, cls.__name__))
ValueError: Cannot convert nan to Fraction.
顺便说一句,您还可以使用float('Inf')
、Decimal('Inf')
或math.inf
(3.5+) 来分配无限数。 (另见math.isinf(...)
)
但是,Fraction('Inf')
或 Fraction(float('inf'))
是不允许的,并且会抛出异常,就像 NaN 一样。
如果您想要一种快速简便的方法来检查一个数字是否既不是 NaN 也不是无限的,您可以使用 math.isfinite(...)
从 Python 3.2+ 开始。
如果您想对复数进行类似检查,cmath
模块包含一组与 math
模块类似的函数和常量:
cmath.isnan(...)
cmath.isinf(...)
cmath.isfinite(...)
(Python 3.2+)
cmath.nan
(Python 3.6+;相当于complex(float('nan'), 0.0)
)
cmath.nanj
(Python 3.6+;相当于complex(0.0, float('nan'))
)
cmath.inf
(Python 3.6+;相当于complex(float('inf'), 0.0)
)
cmath.infj
(Python 3.6+;相当于complex(0.0, float('inf'))
)
【讨论】:
请注意,使用 float('nan) 比使用 np.nan 慢 3 倍,比分配一次 nan = float('nan') 然后使用变量 'nan' 慢大约 6.5 倍以下所有作业(如 abarnert 的回答中所建议的那样)。【参考方案2】:nan = float('nan')
现在你有了常量nan
。
您可以类似地为 decimal.Decimal 创建 NaN 值。:
dnan = Decimal('nan')
【讨论】:
这是对多个 nan 赋值最有效的答案:即只使用一次 float('nan'),然后对所有剩余的赋值使用分配的常量。但是,如果您只执行 nan total 的一两个任务,那么使用 numpy.nan 是最快的。 Python愚蠢的API设计,为什么不添加一个float.nan
常量?【参考方案3】:
使用float("nan")
:
>>> float("nan")
nan
【讨论】:
【参考方案4】:可以从“inf - inf”得到NaN,也可以从大于2e308的数得到“inf”,所以,我一般用:
>>> inf = 9e999
>>> inf
inf
>>> inf - inf
nan
【讨论】:
这个答案不合理地被否决了。我在 .txt 文件中编写了许多小型解析测试,并使用 ast.literal_eval 来获得预期的输出部分。在那里调用 float('nan') 是不可能的,这个答案对我很有帮助。 @VitalikVerhovodov 需要指出的是,从 Python 3.7 开始,不再可能通过ast.literal_eval('1e999-1e999')
获得 NaN 值。有关更改的更多详细信息,请参阅bpo-31778。在过去,ast.literal_eval
似乎能够添加和减去文字,但这只是由于支持复数文字评估的松散输入验证。根据its official documentation,ast.literal_eval
不是为评估涉及运算符的表达式而设计的。【参考方案5】:
您可以通过float('nan')
获取 NaN。
【讨论】:
【参考方案6】:生成 inf 和 -inf 的更一致(且不透明)的方法是再次使用 float():
>> positive_inf = float('inf')
>> positive_inf
inf
>> negative_inf = float('-inf')
>> negative_inf
-inf
请注意,浮点数的大小因架构而异,因此最好避免使用像 9e999 这样的幻数,即使这可能会起作用。
import sys
sys.float_info
sys.float_info(max=1.7976931348623157e+308,
max_exp=1024, max_10_exp=308,
min=2.2250738585072014e-308, min_exp=-1021,
min_10_exp=-307, dig=15, mant_dig=53,
epsilon=2.220446049250313e-16, radix=2, rounds=1)
【讨论】:
以上是关于在没有numpy的python中分配一个变量NaN的主要内容,如果未能解决你的问题,请参考以下文章