Berechnung von großen (Gleitpunkt)Zahlen
-
http://www.ttmath.org/ ist auch sehr fein - Header-Only läuft super mit gcc,VS2008/2010 usw
-
Hallo,
Dankeschön für die vielen Antworten.
Leider habe ich das Problem nicht ganz korrekt beschrieben und deshalb vielleicht auch nicht die passende Antwort erhalten. Also nochmal ein neuer Versuch. Berechnet werden soll die folgende Formel:
2234913546116637/546812681195752981093125556779405341338292357723303109106442651602488249799843980805878294255763456x^25 -
8230855621557725/16687398718132110018711107079449625895333629080911349765211262561111091607661254297054391304192*x^24 + 3480401368169093/127314748520905380391777855525586135065716774604121015664758778084648831235208544136462336*x^23 - 7128643581070363/7770675568902916283677847627294075626569627356208558085007249638955617140820833992704*x^22 + 4885239585279369/237142198758023568227473377297792835283496928595231875152809132048206089502588928*x^21 - 4627605019871349/14474011154664524427946373126085988481658748083205070504932198000989141204992*x^20 + 5865082811361573/1766847064778384329583297500742918515827483896875618958121606201292619776*x^19 - 7823933447521549/431359146674410236714672241392314090778194310760649159697657763987456*x^18 - 936674789841489/13164036458569648337239753460458804039861886925068638906788872192*x^17 + 4526172036750237/1606938044258990275541962092341162602522202993782792835301376*x^16 - 1713828821103303/49039857307708443467467104868809893875799651909875269632*x^15 + 6876158081797715/23945242826029513411849172299223580994042798784118784x^14 -
5138493841735941/2923003274661805836407369665432566039311865085952x^13 +
5954245828809621/713623846352979940529142984724747568191373312x^12 -
2716068399330923/87112285931760246646623899502532662132736x^11 +
3917306946471135/42535295865117307932921825928971026432x^10 -
4451622502140629/20769187434139310514121985316880384x^9 +
1975271885241521/5070602400912917605986812821504x^8 -
2698492929024059/4951760157141521099596496896x^7 +
5559600079402095/9671406556917033397649408x^6 -
8400827854431529/18889465931478580854784x^5 +
8979784754350487/36893488147419103232x^4 -
3247741030714731/36028797018963968x^3 +
380321282273631/17592186044416x^2 -
7553149350887783/2199023255552*x +
8641683254463363/8589934592Das Ergebnis ist der Wert zu einem Polynom. Allerdings erhalte ich dann bei
einem X-Wert von 9959 als Ergebnis 0,03967 und bei
einem X-Wert von 9960 als Ergebnis 0,04295
was nicht korrekt ist, weil das Ergebnis von X=1 und Y=1,00000 bis X=10.000 und Y=0,00000 absteigen muss.Wenn die Aussage von SeppJ für das Beispiel auch noch stimmt, weshalb entsteht von 9959 auf 9960 dann dieser Fehler? Vermutlich ist das vorherige Runden auf 8 Stellen dann doch ein Problem?
Nochmal Danke und viele Grüße!
P S
Ich verwende den Qt-Creator als Entwicklungsumgebung und den gcc als Compiler. Das Gesamtergebnis wird auf 5 Nachkommastellen gerundet benötigt.
-
Wie hast du denn die Rechnung durchgeführt?
Und wo bekommt das Programm eigentlich die Zahlen her? So wie es aussieht, stehen doch schon alle Zahlen im Voraus fest, wo ist also überhaupt das Problem?
-
Bei x=0 kommt da aber 1006024,3371947858249768614768982 raus.
Das sieht irgendwie nach einer Reihenentwicklung aus.
Aber da berechnet man die einzelnen Teile meist geschickter.
-
Die Variable in der Berechnung ist x und gültige Werte dazu liegen im Bereich von 1 - 10.0000.
In die Formel hatte ich Werte von x=1 bis x=10.0000 eingesetzt und die Y-Werte dazu berechnet. Dabei sollte der jeweilige Y-Wert(Ergebnis mit 5 Nachkommastellen) kontinuierlich abfallen und nicht mehr ansteigen...
Deshalb ist die Frage, wenn ich die Berechnung mit mehr als 8 Nachkommastellen durchführen kann, erhalte ich damit auch das gewünschten Ergebnis?
Vielen Dank für die tolle Beteiligung an diesem Beitrag!
-
Bei mir funktioniert das problemlos (VC++ 2013)
#include <iostream> #include <iomanip> #include <limits> #include <cmath> using namespace std; long double calc(long double x) { return (long double)2234913546116637 / (long double)546812681195752981093125556779405341338292357723303109106442651602488249799843980805878294255763456.0L * pow(x, 25) - (long double)8230855621557725 / (long double)16687398718132110018711107079449625895333629080911349765211262561111091607661254297054391304192.0L * pow(x, 24) + (long double)3480401368169093 / (long double)127314748520905380391777855525586135065716774604121015664758778084648831235208544136462336.0L * pow(x, 23) - (long double)7128643581070363 / (long double)7770675568902916283677847627294075626569627356208558085007249638955617140820833992704.0L * pow(x, 22) + (long double)4885239585279369 / (long double)237142198758023568227473377297792835283496928595231875152809132048206089502588928.0L * pow(x, 21) - (long double)4627605019871349 / (long double)14474011154664524427946373126085988481658748083205070504932198000989141204992.0L * pow(x, 20) + (long double)5865082811361573 / (long double)1766847064778384329583297500742918515827483896875618958121606201292619776.0L * pow(x, 19) - (long double)7823933447521549 / (long double)431359146674410236714672241392314090778194310760649159697657763987456.0L * pow(x, 18) - (long double)936674789841489 / (long double)13164036458569648337239753460458804039861886925068638906788872192.0L * pow(x, 17) + (long double)4526172036750237 / (long double)1606938044258990275541962092341162602522202993782792835301376.0L * pow(x, 16) - (long double)1713828821103303 / (long double)49039857307708443467467104868809893875799651909875269632.0L * pow(x, 15) + (long double)6876158081797715 / (long double)23945242826029513411849172299223580994042798784118784.0L * pow(x, 14) - (long double)5138493841735941 / (long double)2923003274661805836407369665432566039311865085952.0L * pow(x, 13) + (long double)5954245828809621 / (long double)713623846352979940529142984724747568191373312.0L * pow(x, 12) - (long double)2716068399330923 / (long double)87112285931760246646623899502532662132736.0L * pow(x, 11) + (long double)3917306946471135 / (long double)42535295865117307932921825928971026432.0L * pow(x, 10) - (long double)4451622502140629 / (long double)20769187434139310514121985316880384.0L * pow(x, 9) + (long double)1975271885241521 / (long double)5070602400912917605986812821504.0L * pow(x, 8) - (long double)2698492929024059 / (long double)4951760157141521099596496896.0L * pow(x, 7) + (long double)5559600079402095 / (long double)9671406556917033397649408.0L * pow(x, 6) - (long double)8400827854431529 / (long double)18889465931478580854784.0L * pow(x, 5) + (long double)8979784754350487 / (long double)36893488147419103232.0L * pow(x, 4) - (long double)3247741030714731 / (long double)36028797018963968.0L * pow(x, 3) + (long double)380321282273631 / (long double)17592186044416.0L * pow(x, 2) - (long double)7553149350887783 / (long double)2199023255552.0L * x + (long double)8641683254463363 / (long double)8589934592; } int main(void) { cout << setiosflags(ios_base::scientific); cout << "Setting cout precision to " << numeric_limits< long double >::digits10 << endl; cout.precision(numeric_limits< long double >::digits10); for (int i = 0; i < 10; ++i) { cout << "x = " << long double(i) << " f(x) = " << calc(long double(i)) << endl; } cout << "\n\nf(9959) = " << calc(long double(9959)) << endl; cout << "\n\nf(9960) = " << calc(long double(9959)) << endl; return 0; }
Ausgabe
Setting cout precision to 15 x = 0.000000000000000e+000 f(x) = 1.006024337194786e+006 x = 1.000000000000000e+000 f(x) = 1.002611091398601e+006 x = 2.000000000000000e+000 f(x) = 9.992405456630456e+005 x = 3.000000000000000e+000 f(x) = 9.959121678264987e+005 x = 4.000000000000000e+000 f(x) = 9.926254314630381e+005 x = 5.000000000000000e+000 f(x) = 9.893798158300950e+005 x = 6.000000000000000e+000 f(x) = 9.861748058165179e+005 x = 7.000000000000000e+000 f(x) = 9.830098918910384e+005 x = 8.000000000000000e+000 f(x) = 9.798845700511376e+005 x = 9.000000000000000e+000 f(x) = 9.767983417723103e+005 f(9959) = 2.338740549736074e+003 f(9960) = 2.338740549736074e+003
Wobei VC++20113
long double
aufdouble
reduziert.
-
Ist das hier vielleicht ein X/Y-Problem?
-
Hallo,
so fängt der Tag gut an Vielen Dank an alle und besonders für das tolle Beispiel von trunc
Ein kleiner Fehler ist noch in dem Beispiel, die Berechnung wurde 2x mit 9959 durchgeführt. Diese Kleinigkeit korrigiert und schon funktioniert es auch bei mir
Nachfolgend noch meine Version die mit dem GCC 4.5.2 erstellt wurde:
g++ main.cpp -o app.exe
main.cpp
#include <iostream> #include <iomanip> #include <limits> #include <cmath> using namespace std; long double calc(long double x) { return (long double)2234913546116637 / (long double)546812681195752981093125556779405341338292357723303109106442651602488249799843980805878294255763456.0L * pow(x, 25) - (long double)8230855621557725 / (long double)16687398718132110018711107079449625895333629080911349765211262561111091607661254297054391304192.0L * pow(x, 24) + (long double)3480401368169093 / (long double)127314748520905380391777855525586135065716774604121015664758778084648831235208544136462336.0L * pow(x, 23) - (long double)7128643581070363 / (long double)7770675568902916283677847627294075626569627356208558085007249638955617140820833992704.0L * pow(x, 22) + (long double)4885239585279369 / (long double)237142198758023568227473377297792835283496928595231875152809132048206089502588928.0L * pow(x, 21) - (long double)4627605019871349 / (long double)14474011154664524427946373126085988481658748083205070504932198000989141204992.0L * pow(x, 20) + (long double)5865082811361573 / (long double)1766847064778384329583297500742918515827483896875618958121606201292619776.0L * pow(x, 19) - (long double)7823933447521549 / (long double)431359146674410236714672241392314090778194310760649159697657763987456.0L * pow(x, 18) - (long double)936674789841489 / (long double)13164036458569648337239753460458804039861886925068638906788872192.0L * pow(x, 17) + (long double)4526172036750237 / (long double)1606938044258990275541962092341162602522202993782792835301376.0L * pow(x, 16) - (long double)1713828821103303 / (long double)49039857307708443467467104868809893875799651909875269632.0L * pow(x, 15) + (long double)6876158081797715 / (long double)23945242826029513411849172299223580994042798784118784.0L * pow(x, 14) - (long double)5138493841735941 / (long double)2923003274661805836407369665432566039311865085952.0L * pow(x, 13) + (long double)5954245828809621 / (long double)713623846352979940529142984724747568191373312.0L * pow(x, 12) - (long double)2716068399330923 / (long double)87112285931760246646623899502532662132736.0L * pow(x, 11) + (long double)3917306946471135 / (long double)42535295865117307932921825928971026432.0L * pow(x, 10) - (long double)4451622502140629 / (long double)20769187434139310514121985316880384.0L * pow(x, 9) + (long double)1975271885241521 / (long double)5070602400912917605986812821504.0L * pow(x, 8) - (long double)2698492929024059 / (long double)4951760157141521099596496896.0L * pow(x, 7) + (long double)5559600079402095 / (long double)9671406556917033397649408.0L * pow(x, 6) - (long double)8400827854431529 / (long double)18889465931478580854784.0L * pow(x, 5) + (long double)8979784754350487 / (long double)36893488147419103232.0L * pow(x, 4) - (long double)3247741030714731 / (long double)36028797018963968.0L * pow(x, 3) + (long double)380321282273631 / (long double)17592186044416.0L * pow(x, 2) - (long double)7553149350887783 / (long double)2199023255552.0L * x + (long double)8641683254463363 / (long double)8589934592; } int main(void) { cout << setiosflags(ios_base::scientific); cout << "Setting cout precision to " << numeric_limits< long double >::digits10 << endl; cout.precision(numeric_limits< long double >::digits10); for (int i = 0; i < 10; ++i) { cout << "x = " << (long double)i << " f(x) = " << calc(i) << endl; } cout << "\n\nf(9959) = " << calc(9959) << endl; cout << "f(9960) = " << calc(9960); return 0; }
Ausgabe
Setting cout precision to 18 x = 0.000000000000000000e+000 f(x) = 1.006024337194785825e+006 x = 1.000000000000000000e+000 f(x) = 1.002611091398601383e+006 x = 2.000000000000000000e+000 f(x) = 9.992405456630455492e+005 x = 3.000000000000000000e+000 f(x) = 9.959121678264987193e+005 x = 4.000000000000000000e+000 f(x) = 9.926254314630381053e+005 x = 5.000000000000000000e+000 f(x) = 9.893798158300950234e+005 x = 6.000000000000000000e+000 f(x) = 9.861748058165179073e+005 x = 7.000000000000000000e+000 f(x) = 9.830098918910383546e+005 x = 8.000000000000000000e+000 f(x) = 9.798845700511375314e+005 x = 9.000000000000000000e+000 f(x) = 9.767983417723102716e+005 f(9959) = 2.323934689140187402e+003 f(9960) = 2.249770189624356135e+003
Wünsche allen noch eine angenehme Woche!
-
Ich hoffe, dir ist klar, was bei
(long double)546812681195752981093125556779405341338292357723303109106442651602488249799843980805878294255763456.0L
intern passiert?!
long double d = (long double)546812681195752981093125556779405341338292357723303109106442651602488249799843980805878294255763456.0L; cout << setprecision(100) << d << endl;
Die Berechnung wird also niemals die Genaugkeit haben, welche durch die 100-Ziffern-Zahl (anscheinend) ausgedrückt werden soll.
-
Th69 schrieb:
Die Berechnung wird also niemals die Genaugkeit haben, welche durch die 100-Ziffern-Zahl (anscheinend) ausgedrückt werden soll.
Daher der nic ("trunc").
-
mit Horner-Schema bekommt man immerhin die hohen Potenzen x^25, x^24 usw weg.