Ответ 1
Так как v.2.7. стандартный математический модуль содержит функцию erf. Это должно быть самым простым способом.
Я могу реализовать функцию ошибки, erf, сам, но я бы предпочел не делать этого. Есть ли пакет python без внешних зависимостей, который содержит реализацию этой функции? Я нашел этот, но это похоже на часть гораздо большего пакета (и это даже не понятно, какой из них).
Так как v.2.7. стандартный математический модуль содержит функцию erf. Это должно быть самым простым способом.
Я рекомендую 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)
Алгоритм из Справочник по математическим функциям, формула 7.1.26.
Я бы порекомендовал вам скачать numpy (иметь эффективную матрицу в python) и scipy (заменитель инструмента Matlab, который использует numpy). Функция erf лежит в scipy.
>>>from scipy.special import erf
>>>help(erf)
Вы также можете использовать функцию erf, определенную в pylab, но это больше предназначено для построения результатов вычислений, которые вы вычисляете с помощью numpy и scipy. Если вы хотите многофункциональное устройство установка этого программного обеспечения вы можете напрямую использовать Python Enthought distribution.
Реализация чистого python может быть найдена в модуле mpmath (http://code.google.com/p/mpmath/)
Из строки документа:
>>> 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
также связаны с функцией ошибки.
У меня есть функция, которая выполняет 10 ^ 5 erf-вызовов. На моей машине...
scipy.special.erf делает это время при 6.1s
erf Справочник по математическим функциям принимает 8.3s
erf Numerical Recipes 6.2 принимает 9.5s
(средние три пробега, код, взятый из предыдущих плакатов).
Чтобы ответить на мой собственный вопрос, я закончил использовать следующий код, адаптированный из версии 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 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
Одно примечание для тех, кто стремится к более высокой производительности: векторизовать, если возможно.
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