2009-05-06 12 views
9

Wir sollen berechnen e^x mit dieser Art der Formel:Berechnung e^x, ohne Funktionen mit

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

ich diesen Code haben bisher:

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

jetzt Mein Problem ist, dass seit faktorielles vom Typ long lang ist, kann ich nicht wirklich eine Zahl größer als 20 speichern ! so was, dass die Programmausgänge lustigen Zahlen geschieht, wenn es diesen Punkt erreicht ..

Die richtige Lösung kann einen X-Wert von 709 höchstens hat so e^709 ausgeben soll: 8.21840746155e + 307

Das Programm ist in C++ geschrieben.

+1

warum nicht factorial ein double machen? –

Antwort

32

Sowohl x^n als auch n! wächst schnell mit n (exponentiell bzw. superexponentiell) und wird bald jeden Datentyp überlaufen, den Sie verwenden. Auf der anderen Seite, x^n/n! geht runter (irgendwann) und du kannst aufhören, wenn es klein ist. Verwenden Sie die Tatsache, dass x^(n + 1)/(n + 1)! = (x^n/n!) * (x/(n + 1)). Wie diese, sagen:

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

(-Code direkt in dieses Feld eingegeben haben, aber ich erwarte, sollte es funktionieren.)

Edit: Beachten Sie, dass der Begriff x^n/n! ist für großes x für eine Weile ansteigend und dann abnehmend. Für x = 709 geht es bis zu ~ 1e + 306 vor dem Abnehmen auf 0, was genau an den Grenzen dessen ist, was double verarbeiten kann (double 's Bereich ist ~ 1e308 und term*x schiebt es um), aber long double funktioniert gut. Natürlich ist Ihr endgültiges Ergebnis e x größer als jeder der Begriffe, also vorausgesetzt, Sie verwenden einen Datentyp groß genug, um das Ergebnis unterzubringen, werden Sie in Ordnung sein.

(für x = 709, können Sie mit der Verwendung von nur double weg, wenn Sie verwenden term = term/n * x, aber es funktioniert nicht für 710.)

+0

+1: Beat mich dazu! – gnovice

+0

Sorry für die Dichte, aber ich kann es nicht bekommen .. Wenn ich X mit 709 ersetze, ist die Antwort 1.8046..e + 016 –

+0

Ja, ich habe eine Notiz auf die Antwort hinzugefügt, um dies zu adressieren. x = 709 liegt an der Grenze dessen, was doppelt gehandhabt werden kann. – ShreevatsaR

4

Was passiert, wenn Sie den Typ factorial von long long zu double ändern?

+0

versucht, e^709 mit factorial vom Typ doppelt zu berechnen produziert: -1. # IND Und die maximale Iteration ich denke, ist 172 –

1

Was Sie hier präsentiert ist eine Anwendung von Horner scheme zu Polynome zu berechnen.

2

Ich kann an eine andere Lösung denken. pow(e,x) = pow(10, m) * b Lassen wo b>=1 und < 10 ist, dann

m = trunc(x * log10(e)) 

wo in log10(e) ein konstanter Faktor ist.

und

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

Damit erhalten Sie:

z = x-m/log10(e) 

, die zwischen 0 bis 3 sein wird, und dann b = pow(e,z) verwenden, wie durch SreevartsR gegeben.

und endgültige Antwort ist

b Base (significant digit) und m Mantisse (Größenordnung).

Dies ist schneller als SreevartsR Ansatz und Sie müssen möglicherweise keine hohen Genauigkeiten verwenden.

Viel Glück.

Dies funktioniert sogar, wenn x kleiner als 0 und ein größerer negativ ist, in diesem Fall wird z zwischen 0 und -3 liegen und dies wird schneller als jeder andere Ansatz sein.

Da z -3 bis 3 ist, und wenn Sie die ersten 20 signifikanten Stellen benötigen, kann der Ausdruck pow (e, z) bis 37 Begriffe erst seit 3 ​​^ 37/37 ausgewertet werden! = ~ 3.2e-26.

+0

Sicher wird es schneller sein - noch schneller wäre es, "exp (x)" zu schreiben - aber es erfüllt nicht die Anforderung, "e^x zu berechnen, ohne irgendwelche Funktionen zu verwenden". :-) – ShreevatsaR

+0

@ShreevatsaR: Eigentlich denke ich, dass es tut - obwohl ich keinen Vorteil aus der Berechnung in Base-10 sehen kann. Wo verwendet diese Lösung _alle Funktionen_? – jpalecek

+0

@jpalecek: pow() ist eine eingebaute Funktion, genau wie exp(). Ich nehme an, die Absicht des ursprünglichen Posters war genau * nicht *, exp() oder andere solche Funktionen zu verwenden (oder vielleicht war sogar die Absicht, die gegebene Serie zu verwenden). – ShreevatsaR