2009-05-06 13 views
9

Se supone que debemos calcular e^x el uso de este tipo de fórmula:Cálculo e^x sin utilizar ninguna función

e^x = 1 + (! X^1/1) + (x^2/2 !) ......

tengo este código hasta ahora:

while (result >= 1.0E-20) 
{ 
    power = power * input; 
    factorial = factorial * counter; 
    result = power/factorial; 
    eValue += result; 
    counter++; 
    iterations++; 
} 

Mi problema ahora es que desde factorial es de tipo long larga, en realidad no puedo almacenar un número mayor que 20 ! así que lo que sucede es que los números divertidas salidas del programa cuando se llega a ese punto ..

La solución correcta puede tener un valor X de un máximo de 709 por lo que e^709 es la Salida: 8.21840746155e + 307

El programa está escrito en C++.

+1

¿por qué no hacer factorial a double? –

Respuesta

32

Ambos x^n y n! crecer rápidamente con n (exponencial y superexponencial respectivamente) y pronto se desbordará cualquier tipo de datos que utilice. Por otro lado, x^n/n! baja (eventualmente) y puedes detenerlo cuando es pequeño. Es decir, use el hecho de que x^(n + 1)/(n + 1)! = (x^n/n!) * (x/(n + 1)). De esta manera, decir:

term = 1.0; 
for(n=1; term >= 1.0E-10; n++) 
{ 
    eValue += term; 
    term = term * x/n; 
} 

(Código escribe directamente en esta caja, pero espero que debería funcionar.)

Editar: Tenga en cuenta que el término x^n/n! es, para x grande, aumentando por un tiempo y luego disminuyendo. Para x = 709, sube a ~ 1e + 306 antes de disminuir a 0, que está justo en los límites de lo que double puede manejar (el rango de double es ~ 1e308 y term*x lo empuja), pero long double funciona bien. Por supuesto, su resultado final e x es más grande que cualquiera de los términos, por lo que suponiendo que está utilizando un tipo de datos lo suficientemente grande como para acomodar el resultado, todo irá bien.

(Para x = 709, usted puede conseguir lejos con el uso justo double si utiliza term = term/n * x, pero no funciona para 710.)

+0

+1: ¡pásame! – gnovice

+0

Lo siento por ser denso pero no puedo obtenerlo ... Cuando sustituyo X con 709, la respuesta es 1.8046..e + 016 –

+0

Sí, agregué una nota a la respuesta para abordar esto. x = 709 está en los límites de lo que puede manejar el doble. – ShreevatsaR

4

¿Qué ocurre si cambia el tipo de factorial de long long a double?

+0

tratando de calcular e^709 con factorial de tipo double producido: -1. # IND Y la iteración máxima supongo que es 172 –

1

Lo que aquí se presenta es una aplicación de Horner scheme para el cálculo de polinomios.

2

Puedo pensar en otra solución. Deje pow(e,x) = pow(10, m) * b donde b es >=1 y < 10, entonces

m = trunc(x * log10(e)) 

donde en log10(e) es un factor constante.

y

b = pow(e,x)/pow(10, m) = pow(e,x)/pow(e,m/log10(e)) = pow (e,x-m/log10(e)) 

Por esto se obtiene:

z = x-m/log10(e) 

que estará en entre 0 a 3 y luego usar b = pow(e,z) dada por SreevartsR.

y respuesta final es

b es base (dígito significativo) y m es mantisa (orden de magnitud).

esto será más rápido que el enfoque SreevartsR y es posible que no necesite utilizar altas precisiones.

Lo mejor de la suerte.

Esto incluso funcionará para cuando x es menor que 0 y un negativo mayor, en ese caso z estará entre 0 y -3 y esto será más rápido que cualquier otro enfoque.

Dado que z es -3 a 3, y si necesita los primeros 20 dígitos significativos, entonces la expresión pow (e, z) se puede evaluar hasta 37 términos solo desde 3^37/37! = ~ 3.2e-26.

+0

Ciertamente será más rápido, incluso más rápido sería escribir 'exp (x)' - pero no cumple el requisito de "calcular e^x sin utilizar ninguna función". :-) – ShreevatsaR

+0

@ShreevatsaR: En realidad, creo que sí, aunque no puedo ver ninguna ventaja al calcular en base-10. ¿Dónde usa esta solución _cualquier función_? – jpalecek

+0

@jpalecek: pow() es una función incorporada, al igual que exp(). Asumo que la intención del póster original era precisamente * no * usar exp() u otras funciones similares (o incluso, tal vez, la intención era usar la serie dada). – ShreevatsaR

Cuestiones relacionadas