W
tschabos schrieb:
ich versuche die eulersche Zahl auf 10 Stellen nach dem Komma genau zu berechnen,
jedoch weiss ich einfach nicht, wie ich die Abbruchbedingung formulieren soll, damit die Berechnung bei 10 Stellen nach dem Komma stoppt.
Hallo tschabos,
das hat mehr mit Mathematik als mit Programmieren zu tun. Mal angenommen, das Programm befindet sind in der Schleife an der Stelle i. Jetzt möchte man feststellen ob man noch weiter als ein vorgegebenes delta vom exakten Wert von e entfernt ist. Dafür stelle ich die Reihenentwicklung für den Rest auf; also das was auf die Summe noch aufgeschlagen werden wird:
rest = k/(i+1) + k/((i+1)(i+2)) + k/((i+1)(i+2)(i+3)) + ...
= k * (1/(i+1) + 1/((i+1)(i+2)) + 1/((i+1)(i+2)(i+3)) + ...)
Die Aufgabe besteht nun darin, abzuschätzen, ob rest < delta ist. Ohne Kenntnis von e ist die Berechnung von rest schwierig, aber ich kann eine zweite Reihe aufstellen - derart
rest2 = k * (1/(i+1) + 1/((i+1)(i+1)) + 1/((i+1)(i+1)*(i+1)) + ...)
vergleicht man die Summanden von rest und rest2, so ist klar, dass rest2>rest ist. Gleichzeitig kann ich rest2 berechnen, da es sich hier um eine geometrische Reihe handelt.
rest2 = k * ( 1/(i+1) /( 1 - 1/(i+1) ) ) = k/i;
Folglich muss man nur noch prüfen, ob k/i<=delta ist, da rest2=k/i und rest<rest2 muss dann auch rest<delta gelten.
Das delta postuliere ich mal auf 1/2*10^(-nk), wenn es auf nk Nachkommastellen genau sein soll.
Hier ein kleines Demoprogramm ...
#include <iostream>
#include <iomanip> // setprecision, setw
#include <cmath> // pow, exp
// -- berechnet e auf nk Nachkommastellen genau
double berechne_e( int nk )
{
double k = 1.0; // k_0 = 1/(0!) = 1
double sum = k;
const double delta = 0.5 * std::pow( 10.0, -nk );
for( int i=1; ; ++i )
{
k /= i; // identisch zu k = (1/double(i) * k)
sum += k; // identisch zu sum = (sum + k);
if( k <= delta * i ) // entspricht k/i <= delta, wenn i>0
break;
}
return sum;
}
namespace math
{
const double e = std::exp(1.0);
}
int main()
{
using namespace std;
cout << "nk Naeherung exakt" << endl;
for( int nk=1; nk<15; ++nk )
{
double e = berechne_e( nk );
// die Ausgabe geschieht auf nk+1 Nachkomastellen genau
cout << setw(2) << right << nk << " " << fixed << setprecision(nk+1) << setw(nk+3) << left << e << setw(15-nk) << " " << math::e << endl;
}
return 0;
}
.. und dessen Ausgabe mit jeweils einer Nachkommastelle mehr, so dass man den Unterschied sieht:
nk Naeherung exakt
1 2.71 2.72
2 2.717 2.718
3 2.7181 2.7183
4 2.71825 2.71828
5 2.718279 2.718282
6 2.7182815 2.7182818
7 2.71828180 2.71828183
8 2.718281826 2.718281828
9 2.7182818283 2.7182818285
10 2.71828182845 2.71828182846
11 2.718281828458 2.718281828459
12 2.7182818284590 2.7182818284590
13 2.71828182845904 2.71828182845905
14 2.718281828459043 2.718281828459045
Gruß
Werner