Ungenauigkeit bei Division mit Double



  • Hallo zusammen,

    stehe gerade vor einem Problem, das mir zwar schon öfters aufgefallen ist, aber mich noch nie wirklich gestört hat:

    Folgender simpler Code (nur als Test):

    int _tmain(int argc, _TCHAR* argv[])
    {
    	double dRes1;
    	double dRes2;
    
    	dRes1 = 1. / 5.;
    	printf("dRes1 = %.20f\n\n", dRes1);
    
    	for (int i = 0; i <= 5; i++)
    		{
    		dRes2 = 62000. + dRes1 * (double)i;
    		printf("i = %d, dRes2 = %.15f\n", i, dRes2);
    		}
    
    	getchar();
    
    	return 0;
    }
    

    Die Ausgabe sieht folgendermaßen aus (lässt sich natürlich auch im Debugger überprüfen):

    dRes1 = 0.20000000000000001000

    i = 0, dRes2 = 62000.000000000000000
    i = 1, dRes2 = 62000.199999999997000
    i = 2, dRes2 = 62000.400000000001000
    i = 3, dRes2 = 62000.599999999999000
    i = 4, dRes2 = 62000.800000000003000
    i = 5, dRes2 = 62001.000000000000000

    Wie kann man nun diese "Ungenauigkeit" abstellen bzw. umgehen?

    Das ganze ist jetzt natürlich nur eine Minimalausgabe meines Problems. Im groben und ganzen muss ich dann mit den Werten, die in der Schleife berechnet werden weiterrechnen, wodurch sich dann die Ungenauigkeit natürlich immer weiter "ausbreitet".

    danke, mfg

    mik



  • Double sind nunmal nicht genau. Es sind Gleitkommazahl mit einer gewissen Genauigkeit und dass lässt sich auch nicht abstellen.
    Sonst schau dir mal Bibliotheken (wie gmp) an, die können dir fast beliebige Genauigkeit geben, aber nur mit erhötem Aufwand.



  • hmm, das hört sich nicht recht gut an 😉
    Da müsste ich dann eine Menge umstellen, wenn ich plötzlich von meinen Double-Werten auf irgendeine andere Bibliothek umsteige...

    Dh. es gibt keinen Trick, mit dem ich zB. einfach nach der 1. Rechnung (1 / 5) einfach alles nach der zB. 4. Nachkommastelle abschneide, so dass ich als Ergebnis dann auch wirklich 0.2 habe?

    Double sind nunmal nicht genau. Es sind Gleitkommazahl mit einer gewissen Genauigkeit und dass lässt sich auch nicht abstellen.

    Kann mir vielleicht irgendwer erklären, woran das liegt, oder einen Link geben, wo das beschrieben wird? Ich verlange ja keine Undinge und Genauigkeit auf 15 Kommastellen, da verwundert es mich schon ein wenig, dass eine "einfache" Rechnung wie eben 1 / 5 schon zu einem solchen Fehler führt...

    danke, mfg





  • suamikim schrieb:

    dass eine "einfache" Rechnung wie eben 1 / 5 schon zu einem solchen Fehler führt...

    1/3 ist ebenso einfach, und wir können es nicht genau darstellen. Das Problem liegt darin, dass double im Binärsystem dargestellt ist, und im binärsystem kann man nur durch potenzen von 2 gut teilen.(in trinären system ist dafür aber 1/3 sehr trivial ;))

    Teilt man die Binäre zahl "11"(dez 3) durch "10"(also 2) kommt am Ende "1.1" raus, (dez 1.5).

    0.2 lässt sich binär nicht gut darstellen. das wäre sowas wie 0.00110011... also periodisch.

    Dazu kommen noch die "normalen" probleme.Irgendwann sind die grenzen der genauigkeit erreicht.



  • Wenns dir nur um das Darstellen geht, kannst du doch die Streams und ihre Manipulatoren benutzen. Die können auch Nachkommestellen abschneiden. Denn letztendlich willst du anscheinend nur dem Anwender z.B. 4 Nachkommastellen zeigen?

    Wenns auch rechnerisch genau sein soll, mußt du die Tips der Kollegen beachten.


Anmelden zum Antworten