可以将数字设置为NaN或无穷大吗?

241 投票
5 回答
382366 浏览
提问于 2025-04-16 14:27

在Python中,能不能把数组中的某个元素设置为NaN(不是一个数字)呢?

另外,能不能把一个变量设置为正无穷大或负无穷大?如果可以的话,有没有什么方法可以检查一个数字是不是无穷大呢?

5 个回答

55

可以把一个数字设置为NaN或无穷大吗?

可以的,实际上有几种方法。里面有些方法不需要额外导入库,而有些则需要用到import。不过在这里,我只会提到标准库和NumPy(虽然NumPy不是标准库,但它是一个非常常用的第三方库)。

下面的表格总结了如何创建一个不是数字(NaN)或正负无穷大的float

╒══════════╤══════════════╤════════════════════╤════════════════════╕
│   result │ NaN          │ Infinity           │ -Infinity          │
│ module   │              │                    │                    │
╞══════════╪══════════════╪════════════════════╪════════════════════╡
│ built-in │ float("nan") │ float("inf")       │ -float("inf")      │
│          │              │ float("infinity")  │ -float("infinity") │
│          │              │ float("+inf")      │ float("-inf")      │
│          │              │ float("+infinity") │ float("-infinity") │
├──────────┼──────────────┼────────────────────┼────────────────────┤
│ math     │ math.nan     │ math.inf           │ -math.inf          │
├──────────┼──────────────┼────────────────────┼────────────────────┤
│ cmath    │ cmath.nan    │ cmath.inf          │ -cmath.inf         │
├──────────┼──────────────┼────────────────────┼────────────────────┤
│ numpy    │ numpy.nan    │ numpy.PINF         │ numpy.NINF         │
│          │ numpy.NaN    │ numpy.inf          │ -numpy.inf         │
│          │ numpy.NAN    │ numpy.infty        │ -numpy.infty       │
│          │              │ numpy.Inf          │ -numpy.Inf         │
│          │              │ numpy.Infinity     │ -numpy.Infinity    │
╘══════════╧══════════════╧════════════════════╧════════════════════╛

关于这个表格有几点说明:

  • float构造函数其实不区分大小写,所以你也可以用float("NaN")float("InFiNiTy")
  • cmathnumpy的常量返回的是普通的Python float对象。
  • numpy.NINF是我知道的唯一一个不需要-的常量。
  • 可以用complexcmath创建复杂的NaN和无穷大:

    ╒══════════╤════════════════╤═════════════════╤═════════════════════╤══════════════════════╕
    │   result │ NaN+0j         │ 0+NaNj          │ Inf+0j              │ 0+Infj               │
    │ module   │                │                 │                     │                      │
    ╞══════════╪════════════════╪═════════════════╪═════════════════════╪══════════════════════╡
    │ built-in │ complex("nan") │ complex("nanj") │ complex("inf")      │ complex("infj")      │
    │          │                │                 │ complex("infinity") │ complex("infinityj") │
    ├──────────┼────────────────┼─────────────────┼─────────────────────┼──────────────────────┤
    │ cmath    │ cmath.nan ¹    │ cmath.nanj      │ cmath.inf ¹         │ cmath.infj           │
    ╘══════════╧════════════════╧═════════════════╧═════════════════════╧══════════════════════╛
    

    带有¹的选项返回的是普通的float,而不是complex

有没有函数可以检查一个数字是否是无穷大?

有的,实际上有几个函数可以用来检查NaN、无穷大,或者既不是NaN也不是无穷大。不过这些预定义的函数不是内置的,使用时总是需要import

╒══════════╤═════════════╤════════════════╤════════════════════╕
│      for │ NaN         │ Infinity or    │ not NaN and        │
│          │             │ -Infinity      │ not Infinity and   │
│ module   │             │                │ not -Infinity      │
╞══════════╪═════════════╪════════════════╪════════════════════╡
│ math     │ math.isnan  │ math.isinf     │ math.isfinite      │
├──────────┼─────────────┼────────────────┼────────────────────┤
│ cmath    │ cmath.isnan │ cmath.isinf    │ cmath.isfinite     │
├──────────┼─────────────┼────────────────┼────────────────────┤
│ numpy    │ numpy.isnan │ numpy.isinf    │ numpy.isfinite     │
╘══════════╧═════════════╧════════════════╧════════════════════╛

再说几句:

  • cmathnumpy的函数也适用于复杂对象,它们会检查实部或虚部是否是NaN或无穷大。
  • numpy的函数也适用于numpy数组以及可以转换为数组的其他类型(比如列表、元组等)。
  • NumPy还有一些函数可以明确检查正负无穷大:numpy.isposinfnumpy.isneginf
  • Pandas提供了两个额外的函数来检查NaNpandas.isnapandas.isnull(不过不仅仅是NaN,它还可以匹配NoneNaT
  • 虽然没有内置函数,但自己创建这些函数其实很简单(这里我没有考虑类型检查和文档):

    def isnan(value):
        return value != value  # NaN is not equal to anything, not even itself
    
    infinity = float("infinity")
    
    def isinf(value):
        return abs(value) == infinity 
    
    def isfinite(value):
        return not (isnan(value) or isinf(value))
    

总结一下这些函数的预期结果(假设输入是一个float):

╒════════════════╤═══════╤════════════╤═════════════╤══════════════════╕
│          input │ NaN   │ Infinity   │ -Infinity   │ something else   │
│ function       │       │            │             │                  │
╞════════════════╪═══════╪════════════╪═════════════╪══════════════════╡
│ isnan          │ True  │ False      │ False       │ False            │
├────────────────┼───────┼────────────┼─────────────┼──────────────────┤
│ isinf          │ False │ True       │ True        │ False            │
├────────────────┼───────┼────────────┼─────────────┼──────────────────┤
│ isfinite       │ False │ False      │ False       │ True             │
╘════════════════╧═══════╧════════════╧═════════════╧══════════════════╛

在Python中,可以把数组的一个元素设置为NaN吗?

在列表中这没问题,你可以随意放入NaN(或无穷大):

>>> [math.nan, math.inf, -math.inf, 1]  # python list
[nan, inf, -inf, 1]

不过如果你想把它放入一个array(比如array.arraynumpy.array),那么数组的类型必须floatcomplex,否则它会试图把它转换成数组的类型!

>>> import numpy as np
>>> float_numpy_array = np.array([0., 0., 0.], dtype=float)
>>> float_numpy_array[0] = float("nan")
>>> float_numpy_array
array([nan,  0.,  0.])

>>> import array
>>> float_array = array.array('d', [0, 0, 0])
>>> float_array[0] = float("nan")
>>> float_array
array('d', [nan, 0.0, 0.0])

>>> integer_numpy_array = np.array([0, 0, 0], dtype=int)
>>> integer_numpy_array[0] = float("nan")
ValueError: cannot convert float NaN to integer
83

是的,你可以使用numpy来实现这个功能。

import numpy as np
a = arange(3,dtype=float)

a[0] = np.nan
a[1] = np.inf
a[2] = -np.inf

a # is now [nan,inf,-inf]

np.isnan(a[0]) # True
np.isinf(a[1]) # True
np.isinf(a[2]) # True
307

使用 float() 将字符串转换为浮点数:

>>> float('NaN')
nan
>>> float('Inf')
inf
>>> -float('Inf')
-inf
>>> float('Inf') == float('Inf')
True
>>> float('Inf') == 1
False

撰写回答