是否有一个适用于Python的erf()的简单实现?

是否有一个适用于Python的erf()的简单实现?,python,math,Python,Math,我可以自己实现错误函数erf,但我不想这样。是否有一个没有外部依赖项的python包包含此函数的实现?我发现了,但这似乎是一些更大软件包的一部分(甚至不清楚是哪一个!)。我建议您下载(在python中使用efficiant matrix)和(一个使用numpy的Matlab工具箱替代品)。erf函数位于scipy中 >>>from scipy.special import erf >>>help(erf) 您也可以使用pylab中定义的erf函数,但这更适用

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

我建议您下载(在python中使用efficiant matrix)和(一个使用numpy的Matlab工具箱替代品)。erf函数位于scipy中

>>>from scipy.special import erf
>>>help(erf)
您也可以使用pylab中定义的erf函数,但这更适用于绘制使用numpy和scipy计算的结果。如果你想要一个一体化的
安装这些软件时,您可以直接使用。

对于Python中的数值函数,我建议使用SciPy,但是如果您想要没有依赖项的函数,这里有一个函数,它的所有输入的错误都小于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)

该算法来自公式7.1.26。

为了回答我自己的问题,我最终使用了以下代码,这些代码改编自我在web上其他地方找到的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

可以在mpmath模块()中找到纯python实现

从文档字符串:

>>> 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
对于大型实数
x
\mathrm{erf}(x)
非常接近1 迅速地:

>>> print erf(3)
0.999977909503001
>>> print erf(5)
0.999999999998463
错误函数是一个奇数函数::

>>> nprint(chop(taylor(erf, 0, 5)))
[0.0, 1.12838, 0.0, -0.376126, 0.0, 0.112838]
:func:
erf
实现任意精度计算和 支持复数::

>>> mp.dps = 50
>>> print erf(0.5)
0.52049987781304653768274665389196452873645157575796
>>> mp.dps = 25
>>> print erf(1+j)
(1.316151281697947644880271 + 0.1904534692378346862841089j)
相关功能

另请参见:func:
erfc
,这对于大型
x
,更为准确, 和:func:
erfi
,它给出
\exp(t^2)

菲涅耳积分:func:
fresnels
和:func:
fresnelc

也与error函数有关。

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

scipy.special.erf使时间为6.1s

erf数学函数手册采用8.3s

erf数字配方6.2需要9.5秒

(三次运行平均值,代码取自上述海报)。

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


对于那些追求更高性能的人,请注意一点:如果可能,矢量化

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)
给出结果

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

# loops
1 loops, best of 3: 2.34 s per loop

SciPy实现了
erf
功能,请参阅。

我必须说,我完全没有安装它。我要求提供一个没有外部依赖项的包是有原因的。努比不是唯一的一个。UMFPack是另一个。编写自己的erf()会更容易!正如我所提到的,他们已经捆绑了您所需要的一切。363MB的许可证占用下载比我想要的30行函数还要多。。。碰巧的是,macports似乎做得很好。正如我所说,它正在重新编译整个gcc。这里有点不对劲!示例应为“import scipy.special as erf”,即去掉第一个“erf”,保留第二个。因为erf是一个函数而不是模块,所以它不应该是导入路径的一部分。“导入scipy.special作为foobar”也可以。“as”是一个方便的选项。如果“from scipy.special import erf”只导入erf函数,就不会那么容易混淆了。你是对的。我编辑了我的答案,以找到x的符号,并用另一种方法解决了这个问题。现在没事了。维基百科上写道:“这本‘手册’是美国联邦政府[雇员]的作品,不受版权保护。”。我在这里给这本书添加了一个更直接的链接:我试图使用这个函数,但将numpy数组传递给x并返回numy数组作为答案,但没有成功。你能重写函数的数组版本吗?那真的很有趣。大概这个多精度实现比使用本机浮点要慢一点?从libm.so(标准c数学库,这里是64位linux)使用ctypes调用erf会下降到5.6s。我还需要1000 s的erf调用。根据你的数字,我选择scipy.special.erf。从那以后你有没有发现更快的?我想知道如何使用查找..FWIW,您如何使用scipy的
erf
函数?使用以下设置:
来自scipy.special import erf;输入numpy作为np;data=np.random.randn(10e5)
,我从:
result=erf(data)
获得非常快的运行时。特别是,在这种情况下,我每个循环得到32ms。获得运行时>1s的唯一方法是我天真地循环一个
numpy
数组中的所有元素。不错,但从2.7开始,我们应该从math import erf中执行
(为了可移植性、准确性、速度等)是否有提供erf的Python模块⁻是的,数学。erfc@Matthew根据文件记载,我认为这是不对的。计算1.0-erf(x)。erf()的倒数形式为SciPy: