是否有一个容易实现的erf()为Python实现?

rog*_*rog 50 python math

我可以实现错误功能,erf,我自己,但我不愿意.是否有一个没有外部依赖项的python包,其中包含此函数的实现?我发现了这个,但这似乎是一些更大的包的一部分(甚至不清楚哪一个!).

gol*_*bor 64

自v.2.7起.标准数学模块包含erf函数.这应该是最简单的方法.

http://docs.python.org/2/library/math.html#math.erf

  • @Matthew 根据文档,我认为这是不正确的。计算结果为 1.0 - erf(x)。erf() 的逆函数在 SciPy 中:/sf/ask/2188637461/ (4认同)
  • @Lori - 是的,math.erfc (2认同)

Joh*_*ook 48

我推荐SciPy用于Python中的数值函数,但是如果你想要一些没有依赖关系的东西,那么对于所有输入,这里的错误误差​​小于1.5*10 -7.

def erf(x):
    # save the sign of x
    sign = 1 if x >= 0 else -1
    x = abs(x)

    # constants
    a1 =  0.254829592
    a2 = -0.284496736
    a3 =  1.421413741
    a4 = -1.453152027
    a5 =  1.061405429
    p  =  0.3275911

    # A&S formula 7.1.26
    t = 1.0/(1.0 + p*x)
    y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*math.exp(-x*x)
    return sign*y # erf(-x) = -erf(x)
Run Code Online (Sandbox Code Playgroud)

该算法来自数学函数手册,公式7.1.26.

  • 来自维基百科:"'手册'是美国联邦政府[员工]的工作,不受版权保护".我在这里更直接地链接到这本书:http://www.math.sfu.ca/~cbm/aands/frameindex.htm (6认同)
  • 你是对的。我编辑了答案,以找到xa的迹象来解决此问题。现在可以了。 (2认同)

Map*_*pad 26

我建议你下载numpy(在python中有效率矩阵)和scipy(一个使用numpy的Matlab工具箱替代品).erf功能在于scipy.

>>>from scipy.special import erf
>>>help(erf)
Run Code Online (Sandbox Code Playgroud)

您也可以使用pylab中定义的erf函数,但这更倾向于用numpy和scipy绘制计算结果.如果您想要这些软件的一体化安装,您可以直接使用Python Enthought发行版.

  • 我不得不说我完全没有安装它。我要求一个没有外部依赖的包是有原因的。Numpy 不是唯一的。UMFPack 是另一个。编写我自己的 erf() 会更容易! (2认同)
  • "从scipy.special import erf"可以减少混淆,因为只导入erf函数. (2认同)

小智 8

A pure python implementation can be found in the mpmath module (http://code.google.com/p/mpmath/)

From the doc string:

>>> from mpmath import *
>>> mp.dps = 15
>>> print erf(0)
0.0
>>> print erf(1)
0.842700792949715
>>> print erf(-1)
-0.842700792949715
>>> print erf(inf)
1.0
>>> print erf(-inf)
-1.0
Run Code Online (Sandbox Code Playgroud)

For large real x, \mathrm{erf}(x) approaches 1 very rapidly::

>>> print erf(3)
0.999977909503001
>>> print erf(5)
0.999999999998463
Run Code Online (Sandbox Code Playgroud)

The error function is an odd function::

>>> nprint(chop(taylor(erf, 0, 5)))
[0.0, 1.12838, 0.0, -0.376126, 0.0, 0.112838]
Run Code Online (Sandbox Code Playgroud)

:func:erf implements arbitrary-precision evaluation and supports complex numbers::

>>> mp.dps = 50
>>> print erf(0.5)
0.52049987781304653768274665389196452873645157575796
>>> mp.dps = 25
>>> print erf(1+j)
(1.316151281697947644880271 + 0.1904534692378346862841089j)
Run Code Online (Sandbox Code Playgroud)

Related functions

See also :func:erfc, which is more accurate for large x, and :func:erfi which gives the antiderivative of \exp(t^2).

The Fresnel integrals :func:fresnels and :func:fresnelc are also related to the error function.


rog*_*rog 6

为了回答我自己的问题,我最终使用了以下代码,这些代码改编自我在网络上其他地方找到的Java版本:

# from: http://www.cs.princeton.edu/introcs/21function/ErrorFunction.java.html
# Implements the Gauss error function.
#   erf(z) = 2 / sqrt(pi) * integral(exp(-t*t), t = 0..z)
#
# fractional error in math formula less than 1.2 * 10 ^ -7.
# although subject to catastrophic cancellation when z in very close to 0
# from Chebyshev fitting formula for erf(z) from Numerical Recipes, 6.2
def erf(z):
    t = 1.0 / (1.0 + 0.5 * abs(z))
        # use Horner's method
        ans = 1 - t * math.exp( -z*z -  1.26551223 +
                            t * ( 1.00002368 +
                            t * ( 0.37409196 + 
                            t * ( 0.09678418 + 
                            t * (-0.18628806 + 
                            t * ( 0.27886807 + 
                            t * (-1.13520398 + 
                            t * ( 1.48851587 + 
                            t * (-0.82215223 + 
                            t * ( 0.17087277))))))))))
        if z >= 0.0:
            return ans
        else:
            return -ans
Run Code Online (Sandbox Code Playgroud)

  • 很好,但从2.7开始我们应该从数学导入erf`(为了便携性,准确性,速度等) (2认同)

met*_*ore 6

我有一个函数可以执行10 ^ 5个erf调用.在我的机器上......

scipy.special.erf的时间为6.1秒

erf数学函数手册需要8.3s

erf Numerical Recipes 6.2需要9.5秒

(三个平均值,代码取自上面的海报).


8on*_*ne6 5

给那些追求更高性能的人的一个注意事项:如果可能的话,进行矢量化。

import numpy as np
from scipy.special import erf

def vectorized(n):
    x = np.random.randn(n)
    return erf(x)

def loopstyle(n):
    x = np.random.randn(n)
    return [erf(v) for v in x]

%timeit vectorized(10e5)
%timeit loopstyle(10e5)
Run Code Online (Sandbox Code Playgroud)

给出结果

# vectorized
10 loops, best of 3: 108 ms per loop

# loops
1 loops, best of 3: 2.34 s per loop
Run Code Online (Sandbox Code Playgroud)