Je peux implémenter la fonction d'erreur, erf, moi-même, mais je préfère ne pas le faire. Existe-t-il un paquet python sans dépendances externes qui contient une implémentation de cette fonction? J'ai trouvé this mais cela semble faire partie d'un paquet beaucoup plus grand (et ce n'est même pas clair lequel!).
Depuis la v.2.7. le module mathématique standard contient la fonction erf . Cela devrait être le moyen le plus simple.
Je recommande SciPy pour les fonctions numériques en Python, mais si vous voulez quelque chose sans dépendances, voici une fonction avec une erreur d'erreur inférieure à 1,5 * 10-sept pour toutes les entrées.
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)
L'algorithme provient de Handbook of Mathematical Functions , formule 7.1.26.
Je vous recommande de télécharger numpy (pour avoir une matrice efficace en python) et scipy (un substitut de la boîte à outils Matlab, qui utilise numpy). La fonction erf réside dans scipy.
>>>from scipy.special import erf
>>>help(erf)
Vous pouvez également utiliser la fonction erf définie dans pylab, mais elle est plus destinée à tracer les résultats des choses que vous calculez avec numpy et scipy. Si vous souhaitez une installation tout-en-un de ces logiciels, vous pouvez utiliser directement le distribution Python Enthought .
Une implémentation pure python peut être trouvée dans le module mpmath ( http://code.google.com/p/mpmath/ )
De la chaîne doc:
>>> 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
Pour les vrais grands x
, \mathrm{erf}(x)
approche 1 très rapidement ::
>>> print erf(3)
0.999977909503001
>>> print erf(5)
0.999999999998463
La fonction d'erreur est une fonction étrange ::
>>> nprint(chop(taylor(erf, 0, 5)))
[0.0, 1.12838, 0.0, -0.376126, 0.0, 0.112838]
: func: erf
implémente une évaluation de précision arbitraire et supporte les nombres complexes ::
>>> mp.dps = 50
>>> print erf(0.5)
0.52049987781304653768274665389196452873645157575796
>>> mp.dps = 25
>>> print erf(1+j)
(1.316151281697947644880271 + 0.1904534692378346862841089j)
Fonctions connexes
Voir aussi: func: erfc
, qui est plus précis pour les grands x
, et: func: erfi
qui donne l'antidérivative de \exp(t^2)
.
Les intégrales de Fresnel: func: fresnels
et: func: fresnelc
sont également liées à la fonction d'erreur.
J'ai une fonction qui fait 10 ^ 5 appels erf. Sur ma machine ...
scipy.special.erf fait le temps à 6.1s
erf Handbook of Mathematical Functions prend 8.3s
erf Numerical Recipes 6.2 prend 9.5s
(moyennes sur trois séries, code tiré des affiches ci-dessus).
Pour répondre à ma propre question, j'ai fini par utiliser le code suivant, adapté d'une version Java que j'ai trouvée ailleurs sur le web:
# 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
Une remarque pour ceux qui visent des performances plus élevées: vectoriser, si possible.
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)
donne des résultats
# vectorized
10 loops, best of 3: 108 ms per loop
# loops
1 loops, best of 3: 2.34 s per loop