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/23945242826029513411849172299223580994042798784118784
    x^14 -
    5138493841735941/2923003274661805836407369665432566039311865085952x^13 +
    5954245828809621/713623846352979940529142984724747568191373312
    x^12 -
    2716068399330923/87112285931760246646623899502532662132736x^11 +
    3917306946471135/42535295865117307932921825928971026432
    x^10 -
    4451622502140629/20769187434139310514121985316880384x^9 +
    1975271885241521/5070602400912917605986812821504
    x^8 -
    2698492929024059/4951760157141521099596496896x^7 +
    5559600079402095/9671406556917033397649408
    x^6 -
    8400827854431529/18889465931478580854784x^5 +
    8979784754350487/36893488147419103232
    x^4 -
    3247741030714731/36028797018963968x^3 +
    380321282273631/17592186044416
    x^2 -
    7553149350887783/2199023255552*x +
    8641683254463363/8589934592

    Das 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.


  • Mod

    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 auf double 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.


Anmelden zum Antworten