具有无穷大的复数的 numpy 平均值
numpy mean of complex numbers with infinities
numpy 似乎不是复无穷大的好朋友
虽然我们可以评估:
In[2]: import numpy as np
In[3]: np.mean([1, 2, np.inf])
Out[3]: inf
下面的结果比较繁琐:
In[4]: np.mean([1 + 0j, 2 + 0j, np.inf + 0j])
Out[4]: (inf+nan*j)
...\_methods.py:80: RuntimeWarning: invalid value encountered in cdouble_scalars
ret = ret.dtype.type(ret / rcount)
我不确定虚部对我有意义。但如果我错了,请发表评论。
对在 numpy 中与复杂的无限交互有任何见解吗?
当您 运行 数组中带有 np.inf
的函数时,结果将是 np.mean
或其他函数(例如 np.max()
)的无限对象。但是在这种情况下计算 mean()
,因为你有复数并且无穷大复数被定义为 复数平面中的一个无限数,其复参数未知或未定义 ,您得到 non*j
作为虚部。
为了解决这个问题,您应该忽略此类数学运算中的无穷项。您可以使用 isfinite()
函数来检测它们并将该函数应用于有限项:
In [16]: arr = np.array([1 + 0j, 2 + 0j, np.inf + 0j])
In [17]: arr[np.isfinite(arr)]
Out[17]: array([ 1.+0.j, 2.+0.j])
In [18]: np.mean(arr[np.isfinite(arr)])
Out[18]: (1.5+0j)
因为类型提升。
当您将复数除以实数时,例如 (inf + 0j) / 2
,(实数)除数会提升为 2 + 0j
。
并且通过复数除法,虚部等于(0 * 2 - inf * 0) / 4
。注意这里的 inf * 0
是一个不确定的形式,它的计算结果是 NaN
。这使得虚部 NaN
.
回到主题。当numpy
计算复数数组的均值时,它真的没有试图做任何聪明的事情。首先,它使用 "addition" 操作减少数组,获得总和。之后,总和除以计数。此和在实部包含 inf
,当除数(计数)从整数类型提升为复数浮点数时会导致上述问题。
编辑:关于解决方案的一句话
IEEE 浮点数 "infinity" 确实是一个非常原始的结构,表示像 1 / 0
这样的不确定形式。这些形式不是常数,而是可能的极限。特殊的 inf
或 NaN
"floating point numbers" 是占位符,用于通知您存在不确定形式。它们对极限的存在或类型没有任何影响,您必须根据数学上下文来确定。
即使对于实数,潜在限制也可能取决于您接近限制的方式。表面的 1 / 0
形式可以达到正无穷大或负无穷大。在复杂的平面上,事情甚至更加复杂(嗯)。例如,您可以 运行 进入分支切割和(不同种类的)奇点。没有适合所有人的通用解决方案。
Tl;dr:修复ambiguous/incomplete/corrupted数据中的底层问题,或者证明最终的计算结果可以承受这种损坏(可能发生)。
解决方案
为了计算平均值,我们将总和除以一个实数。由于类型提升(见下文),这种划分会导致问题。为了避免类型提升,我们可以手动对总和的实部和虚部分别执行此除法:
n = 3
s = np.sum([1 + 0j, 2 + 0j, np.inf + 0j])
mean = np.real(s) / n + 1j * np.imag(s) / n
print(mean) # (inf+0j)
理由
这个问题与 numpy 无关,而是与执行复数除法的方式有关。观察 ((1 + 0j) + (2 + 0j) + (np.inf + 0j)) / (3+0j)
也会导致 (inf+nanj)
.
结果需要分为实部和虚部。对于除法,两个操作数都会提升为复数,即使您除以实数也是如此。所以基本上划分是:
a + bj
--------
c + dj
除法运算不知道d=0
。因此,要将结果分为实部和虚部,必须去掉分母中的 j
。这是通过将分子和分母与复共轭相乘来完成的:
a + bj (a + bj) * (c - dj) ac + bd + bcj - adj
-------- = --------------------- = ---------------------
c + dj (c + dj) * (c - dj) c**2 + d**2
现在,如果 a=inf
和 d=0
项 a * d * j = inf * 0 * j = nan * j
。
numpy 似乎不是复无穷大的好朋友
虽然我们可以评估:
In[2]: import numpy as np
In[3]: np.mean([1, 2, np.inf])
Out[3]: inf
下面的结果比较繁琐:
In[4]: np.mean([1 + 0j, 2 + 0j, np.inf + 0j])
Out[4]: (inf+nan*j)
...\_methods.py:80: RuntimeWarning: invalid value encountered in cdouble_scalars
ret = ret.dtype.type(ret / rcount)
我不确定虚部对我有意义。但如果我错了,请发表评论。
对在 numpy 中与复杂的无限交互有任何见解吗?
当您 运行 数组中带有 np.inf
的函数时,结果将是 np.mean
或其他函数(例如 np.max()
)的无限对象。但是在这种情况下计算 mean()
,因为你有复数并且无穷大复数被定义为 复数平面中的一个无限数,其复参数未知或未定义 ,您得到 non*j
作为虚部。
为了解决这个问题,您应该忽略此类数学运算中的无穷项。您可以使用 isfinite()
函数来检测它们并将该函数应用于有限项:
In [16]: arr = np.array([1 + 0j, 2 + 0j, np.inf + 0j])
In [17]: arr[np.isfinite(arr)]
Out[17]: array([ 1.+0.j, 2.+0.j])
In [18]: np.mean(arr[np.isfinite(arr)])
Out[18]: (1.5+0j)
因为类型提升。
当您将复数除以实数时,例如 (inf + 0j) / 2
,(实数)除数会提升为 2 + 0j
。
并且通过复数除法,虚部等于(0 * 2 - inf * 0) / 4
。注意这里的 inf * 0
是一个不确定的形式,它的计算结果是 NaN
。这使得虚部 NaN
.
回到主题。当numpy
计算复数数组的均值时,它真的没有试图做任何聪明的事情。首先,它使用 "addition" 操作减少数组,获得总和。之后,总和除以计数。此和在实部包含 inf
,当除数(计数)从整数类型提升为复数浮点数时会导致上述问题。
编辑:关于解决方案的一句话
IEEE 浮点数 "infinity" 确实是一个非常原始的结构,表示像 1 / 0
这样的不确定形式。这些形式不是常数,而是可能的极限。特殊的 inf
或 NaN
"floating point numbers" 是占位符,用于通知您存在不确定形式。它们对极限的存在或类型没有任何影响,您必须根据数学上下文来确定。
即使对于实数,潜在限制也可能取决于您接近限制的方式。表面的 1 / 0
形式可以达到正无穷大或负无穷大。在复杂的平面上,事情甚至更加复杂(嗯)。例如,您可以 运行 进入分支切割和(不同种类的)奇点。没有适合所有人的通用解决方案。
Tl;dr:修复ambiguous/incomplete/corrupted数据中的底层问题,或者证明最终的计算结果可以承受这种损坏(可能发生)。
解决方案
为了计算平均值,我们将总和除以一个实数。由于类型提升(见下文),这种划分会导致问题。为了避免类型提升,我们可以手动对总和的实部和虚部分别执行此除法:
n = 3
s = np.sum([1 + 0j, 2 + 0j, np.inf + 0j])
mean = np.real(s) / n + 1j * np.imag(s) / n
print(mean) # (inf+0j)
理由
这个问题与 numpy 无关,而是与执行复数除法的方式有关。观察 ((1 + 0j) + (2 + 0j) + (np.inf + 0j)) / (3+0j)
也会导致 (inf+nanj)
.
结果需要分为实部和虚部。对于除法,两个操作数都会提升为复数,即使您除以实数也是如此。所以基本上划分是:
a + bj
--------
c + dj
除法运算不知道d=0
。因此,要将结果分为实部和虚部,必须去掉分母中的 j
。这是通过将分子和分母与复共轭相乘来完成的:
a + bj (a + bj) * (c - dj) ac + bd + bcj - adj
-------- = --------------------- = ---------------------
c + dj (c + dj) * (c - dj) c**2 + d**2
现在,如果 a=inf
和 d=0
项 a * d * j = inf * 0 * j = nan * j
。