>>> from scipy.special import erf
>>> print (erf(0.j))
__main__:1: RuntimeWarning: invalid value encountered in erf
0j
这个警告只打印一次(即使我做scipy.special.errprint(0)
),但我不明白为什么它会打印出来。实际上,0.j
与0.
的编号相同,并且该编号没有任何问题。
我想有两个问题: 1)有没有办法压制这个警告? 2)这个警告是错误的,还是我错过了什么?
更新
我(我想)跟踪了scipy源代码树中的错误函数。它位于:scipy/special/specfun/specfun.f
(subroutine CERROR
)。此函数不会引发警告(从简单的fortran程序调用时它可以正常工作)。
答案 0 :(得分:1)
您可以使用numpy.seterr
关闭警告:
numpy.seterr(invalid='ignore')
0.j
与0.
不同。前者是一个复数,后者只是一个浮点数。
>>> type(0.j)
<class 'complex'>
>>> type(0.)
<class 'float'>
复杂的erf和real erf使用不同的算法,例如
>>> erf(complex(1))
(0.84270079294971512+0j)
>>> erf(1)
0.84270079294971478
由于真正的erf和复杂的erf使用不同的算法,复杂的erf中的一些警告将不会出现在真实的erf中。如果我们检查Fortran implementation,我们会找到:
SUBROUTINE CERROR(Z,CER)
C ...
Z1=Z
C ...
CS=Z1
CR=Z1
DO 10 K=1,120
CR=CR*Z1*Z1/(K+0.5D0)
CS=CS+CR
IF (CDABS(CR/CS).LT.1.0D-15) GO TO 15
10 CONTINUE
特别地,Z = 0 + 0j,因此Z1 = 0 + 0j,因此在循环之前CS = CR = 0 + 0j。在循环的第一次迭代中,我们得到:
然后条件需要CR / CS,这是一个0/0,这是一个无效的浮点运算,因而是警告。
这是一个小问题,可以通过检查开头是否Z == 0来轻松“修复”。如果您发现此行为不稳定,可以report a bug。