Hilfe! 0.2 - 0.2 < 0
-
Ich habe ein Problem mit 2 double-Variablen. Haben beispielsweise beide den Wert 0.2, und ich ziehe sie voneinander ab, so erhalte ich -1.11022 * 10^-16 anstelle von 0. Was kann ich dagegen tun?
-
Hallo
Da gibt es immer Probleme, weil irgendwelche Kommastellen mitgerechnet werden. Ich habe da mal Stunden mit einer if-Abfrage verbracht.
Vielleicht wissen die Profis ja Hilfe.
chrische
-
double-Variablen sind beim Subtrahieren ungenau. Außerdem kann der Wert 0.2 binär nicht dargestellt werden, stattdessen wird ein sehr ähnlicher Wert verwendet. Die beiden Fehler pflanzen sich in allen weiteren Rechnungen fort. Die Ausgabestreams von C++ zeigen aber trotzdem 0.2 an, weil sie eine festgelegte Anzahl an Nachkommastellen haben. In Wirklichkeit hat die Variable aber einen anderen Wert als 0.2. Bei floats und doubles sollte man deswegen nie auf == testen sondern überprüfen, ob zwei Werte ähnlich sind (mit >= und <=).
geloescht
-
Hehe, schön nur muss ich testen, ob die Differenz der beider kleiner 0 ist. Lösungsvorschläge?
-
Hallo
Benutz <=.
chrische
-
Das nützt mir doch nichts. Folgendes Konstrukt habe ich:
rest = w1 - w2;
if( rest<0 ) ...Wenn ich das ersetze durch
if( !(rest>=0) ) ...
bleibt das Problem bestehen.
-
Teste nicht die Differenz der beiden Zahlen, sondern teste die Zahlen direkt gegeneinander. Die Ungleichung a - b < 0 kann man in a > b umformen. Je nach deiner Anwendung braucht man vielleicht noch std::abs() aus <cmath>. Das sollte zumindest den Subtraktions-Fehler rausnehmen (Fehler mit evt. nicht darstellbaren Zahlen sind immer noch da).
geloescht
-
Evolver schrieb:
Hehe, schön nur muss ich testen, ob die Differenz der beider kleiner 0 ist. Lösungsvorschläge?
4.0 - 6.0 ist kleiner Null. Also sind die Werte gleich!? Ich glaub, ich bin im falschen Universum

Nein, erstmal musst Du festlegen, wieviel Unterscheid in den Zahlen noch als gleich gelten darf. Nehmen wir an, Du arbeitest mit Metern und hättest gerne eine Genauigkeit von einem Millimeter. Dann ist 0.001 und 0.0011 etwa das selbe.
Wenn man jetzt davon ausgeht, dass Du mit den Zahlen auch noch rechnest, sollte darf die Genauigkeit auch etwas genauer ausfallen, um Rundungsfehler zu verringern. In der Ausgabe kann man immernoch brachial alles hinter der dritten Stelle wegrunden.
Dann sieht ein Vergleich so aus:
const double MAXDELTA = 0.0000001
double a = 0.001, b = 0.00011;if( abs(a-b) <= MAXDELTA ) printf( "Die Werte sind [etwa] gleich" ); else printf( "Die Werte sind verschieden" );Das kannst Du dann in eine inline-Funktion packen:
inline bool equal( double a, double b ) return abs( a-b ) <= MAXDELTA;und anschließend in Deinem Programm nutzen:
if( equals( a, b ) ) printf( "Die Werte sind [etwa] gleich" ); else printf( "Die Werte sind verschieden" );Rechnen mit Doubles macht Spaß, gibt viele schöne Möglichkeiten, sein Ergebnis anständig zu versauen.
-
Hmm, ich bin am verzweifeln. Auch das funktioniert nicht. Wahrscheinlich sitz ich heut schon zu lang davor, um den Fehler zu finden.
#define MAXDIFF 0.00001 ... double rest_g = TA->g_lv; for(int i=0; i<anzX; i++) { if(TA->x[index[i]]==LEER) rest_g -= g[index[i]]; if(abs(rest_g)<=MAXDIFF) { TA->alpha = i; break; } } ...So funktioniert der Vergleich noch nichtmal, wenn ich ganzzahlige Werte eingebe. Wo liegt denn mein Fehler?
-
Aso:
if((rest_g<0) && (abs(rest_g)>MAXDIFF))
-
Evolver schrieb:
Hmm, ich bin am verzweifeln. Auch das funktioniert nicht. Wahrscheinlich sitz ich heut schon zu lang davor, um den Fehler zu finden.
#define MAXDIFF 0.00001 ... double rest_g = TA->g_lv; for(int i=0; i<anzX; i++) { if(TA->x[index[i]]==LEER) rest_g -= g[index[i]]; if(abs(rest_g)<=MAXDIFF) { TA->alpha = i; break; } } ...So funktioniert der Vergleich noch nichtmal, wenn ich ganzzahlige Werte eingebe. Wo liegt denn mein Fehler?
Hier findet kein Vergleich auf in Relation zu 0 statt, sondern hier wird gefragt, ob etwas kleiner 0 ist. -1000 ist auch kleiner als Null, aber liegt ausserhalb Deines Deltas.
Evolver schrieb:
if((rest_g<0) && (abs(rest_g)>MAXDIFF))Was machst Du, wenn rest_g positiv ist, aber trotzdem im Bereich von MaxDelta liegt? Dann greift die Bedingung nicht!?
Was willst Du denn überhaupt vergleichen, möchtest Du Fragen, ob etwas etwa 0 ist, dann benutze doch einfach die Equals-Funktion, die ich oben notiert habe.
Oder möchtest Du Fragen, ob etwas kleiner 0 ist und weiter als MAXDELTA von 0 entfernt?if( (rest_g<0) && !Equals( rest_g, 0 ) ) ... // entspricht rest_g < 0 für integersoder etwas spezialisierter (=> schneller):
if( (rest_g<0) && rest_g < (-MAXDELTA) ) ) ... // entspricht rest_g < 0 für integersIch hoffe Dir bei Deinem Problem helfen zu können, aber ich weiß nicht genau weiß, was Dein Problem letztendlich überhaupt ist/war?
Falls nicht, beschreib' es bitte genauer, das erspart das Rumraten und beschleunigt für Dich die Antwort