Am 07.04.2023 um 20:51 schrieb Walter H.:
> ich würd geren eine andere Zahl berechnen: die Basis des nat. Logarithmus
> e = 2.71828182...
> gibt es hier etwas besseres (schnelleres) als das
> e = 1 + 1/1! + 1/2! + ...
Ich nehm mal an, dass 1 / n! so schnell so klein wird, dass es
repräsentierbar Null ergibt ehe deine Fakultät explodiert, dass
die einen FP-Überlauf ergibt.
Aber solltest Du FP-Zahlen verwenden, dann müsstest Du um mög-
lichst exakt zu bleiben für die 1/N! ein Array bilden dass vor
0.0 endet und vom kleinsten Wert ausgehend fortlaufend addiert,
dass Du die maximale Präzision hast.
Ich hab das mal in C++20 geschrieben; in C ginge es dann analog:
#include <iostream>
#include <vector>
#include <numeric>
#include <numbers>
using namespace std;
int main()
{
cout << "C++'s e:" << hexfloat << numbers::e_v<double> << endl;
for( int reverse = 1; reverse >= 0; --reverse )
{
vector<double> recFacts;
recFacts.reserve( 200 );
double f = 1.0;
for( int i = 1; 1.0 / (f *= i); ++i )
recFacts.emplace_back( 1.0 / f );
double e;
if( reverse )
e = accumulate( recFacts.crbegin(), recFacts.crend(), 0.0 ) + 1.0;
else
e = 1.0 + accumulate( recFacts.cbegin(), recFacts.cend(), 0.0 );
cout << (reverse ? "reverse: " : "forward: ") << e << endl;
}
}
Das gibt bei mir aus:
C++'s e:0x1.5bf0a8b145769p+1
reverse: 0x1.5bf0a8b145769p+1
forward: 0x1.5bf0a8b14576ap+1
Wie man sieht ist die Lösung mit der umgekehrten Reihenfolge Bit
-identisch exakt das was numbers::e_v<double> auch ist. Die Lösung
nach vorne ist ein klein wenig ungenauer.