2009-01-19 19 views

Respuesta

24

Yo recomendaría que descargues numpy (para tener una matriz efficiant en python) y scipy (un sustituto de Matlab toolbox, que usa numpy). La función erf se encuentra en scipy.

>>>from scipy.special import erf 
>>>help(erf) 

También puede utilizar la función erf se define en pylab, pero esto es más destinados a trazar los resultados de las cosas que calcular con numpy y scipy. Si desea una instalación todo en uno de estos software, puede usar directamente el Python Enthought distribution.

+0

SciPy es el Motherload de programa digital para Python. Pero comenzar a usarlo puede ser un poco desafiante. Empieza por mirar http://www.scipy.org/ –

+1

Tengo que decir que no pude instalarlo. Había una razón por la que pedí un paquete sin dependencias externas. Numpy no es el único. UMFPack es otro. ¡Será más fácil escribir mi propio erf()! – rog

+1

prueba Python Enthought como mencioné, han agrupado todo lo que necesitas. – Mapad

41

Recomiendo SciPy para funciones numéricas en Python, pero si quiere algo sin dependencias, aquí hay una función con un error de menos de 1.5 * 10 -7 para todas las entradas.

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) 

El algoritmo procede de Handbook of Mathematical Functions, fórmula 7.1.26.

+0

Este código da un error de división por cero para erf (0.0). – rog

+0

Tienes razón. Edité mi respuesta para encontrar el signo de x una forma diferente de solucionar este problema. Ahora esta bien. –

+6

de wikipedia: "el 'manual' es el trabajo del gobierno federal de los EE. UU. [Empleados], no protegido por derechos de autor". Estoy poniendo aquí un enlace más directo al libro: http://www.math.sfu.ca/~cbm/aands/frameindex.htm – mariotomo

6

para responder a mi propia pregunta, he terminado usando el siguiente código, adaptado de una versión de Java que encontré en otro lugar en la 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 
+0

Agradable, pero a partir del 2.7 deberíamos hacer 'desde math import erf' (para portabilidad, precisión, velocidad, etc.) – smci

7

Una aplicación Python puro se puede encontrar en el módulo mpmath (http://code.google.com/p/mpmath/)

Desde la cadena de documentación:

>>> 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 

Para grandes verdadera x, \mathrm{erf}(x) approache s 1 muy rápidamente ::

>>> print erf(3) 
0.999977909503001 
>>> print erf(5) 
0.999999999998463 

la función de error es una función impar ::

>>> nprint(chop(taylor(erf, 0, 5))) 
[0.0, 1.12838, 0.0, -0.376126, 0.0, 0.112838] 

: func: erf implementa la evaluación de precisión arbitraria y soporta números complejos ::

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

Funciones relacionadas

Consulte también: func: erfc, que es más preciso para grandes x, y : func: erfi que da la primitiva de \exp(t^2).

Las integrales de Fresnel: func: fresnels y: func: fresnelc también están relacionadas con la función de error.

+0

eso es realmente interesante. ¿presumiblemente esta implementación de precisión múltiple es un poco más lenta que usar punto flotante nativo? – rog

7

Tengo una función que hace 10^5 llamadas erf. En mi máquina ...

scipy.special.erf hace la hora en 6.1s

Handbook of Mathematical Functions erf toma 8.3s

ERF Numerical Recipes 6.2 toma (promedios de tres carreras, código tomadas desde arriba posters) 9.5s

.

+1

erf llamado con ctypes de libm.so (la biblioteca matemática estándar c, 64 bit linux aquí) pasa a 5.6s. – meteore

+0

También necesito miles de llamadas Erf. De acuerdo con sus números voy con scipy.special.erf. ¿Has encontrado algo más rápido desde entonces? Me he preguntado sobre el uso de una búsqueda .. – jtlz2

+1

FWIW, ¿cómo estás usando la función 'erf' de scipy? Con la siguiente configuración: 'from scipy.special import erf; importar numpy como np; data = np.random.randn (10e5) ', obtengo tiempos de ejecución muy rápidos desde:' result = erf (data) '. En particular, obtengo 32ms por ciclo en ese caso. La única forma en que obtengo tiempos de ejecución> 1 es si ingenuamente repito todos los elementos en una matriz 'numpy'. – 8one6

4

Una nota para aquellos que quieran para un mayor rendimiento: vectorizar, si es posible.

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) 

da resultados

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

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