scipy.special.erf使用0.j引发运行时警告

时间:2012-07-12 13:34:41

标签: python algorithm scipy

>>> from scipy.special import erf
>>> print (erf(0.j))
__main__:1: RuntimeWarning: invalid value encountered in erf
0j

这个警告只打印一次(即使我做scipy.special.errprint(0)),但我不明白为什么它会打印出来。实际上,0.j0.的编号相同,并且该编号没有任何问题。

我想有两个问题: 1)有没有办法压制这个警告? 2)这个警告是错误的,还是我错过了什么?

更新

我(我想)跟踪了scipy源代码树中的错误函数。它位于:scipy/special/specfun/specfun.fsubroutine CERROR)。此函数不会引发警告(从简单的fortran程序调用时它可以正常工作)。

1 个答案:

答案 0 :(得分:1)

您可以使用numpy.seterr关闭警告:

    numpy.seterr(invalid='ignore')

0.j0.不同。前者是一个复数,后者只是一个浮点数。

>>> 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←CR×Z1 2 /(K + 0.5)= 0 + 0j
  • CS←CS + CR = 0 + 0j

然后条件需要CR / CS,这是一个0/0,这是一个无效的浮点运算,因而是警告。

这是一个小问题,可以通过检查开头是否Z == 0来轻松“修复”。如果您发现此行为不稳定,可以report a bug