Hallo Hier ein Beispiel: float f = 3,593; float fa = 0; char c; for (c=0;c<10;c++) fa+=f; fa/=10; if (f==fa) ist nie wahr - warum nicht? Gruss H:V
Weil floats eben auch auf Dualzahlen aufbauen, und deswegen (f/10)*10 nicht gleich f sein muss. (Division durch 5 geht nicht auf...) Manche Programmiersprachen (z.B. SML) bringen deswegen erst garkeinen Gleichheitsoperator für floats/double mit, um solche Fehler zu vermeiden. Abhilfe: if (fabs(f-fa) < 0.0000001) { ... /Ernst
Dezimale Zahlen mit Nachkommastellen sind oft nicht exakt im binären Fliesskommaformat darstellbar. Die Folge sind Rundungsfehler. Versuch als Übung mal, die Zahl 0,1 als Summe von 1/(2**n) darzustellen, also 1/16 + 1/32 + ...
geht net weil duch die binäre darstellung rechenfehler entstehen. dein taschenrechner lügt wenn er sagt 0,2+0,2+0,2+0,2+0,2-1,2 = 0. hab jetzt kein weblink zu dem problem... was du machen kannnst ist: if(abs(f-fa)<0.001 oder so. nochwas: niemals floats als zähler verwenden. float f; int i; for(f=0;f<=5;f+=0.1) pfui! lieber: for(i=0;i<=50;i++) { f=i/10; }
Ausgerechnet der Taschenrechner lügt nicht - denn der arbeitet wahrscheinlich dezimal. Hat's ja nicht eilig.
A.K. wrote: > Ausgerechnet der Taschenrechner lügt nicht - denn der arbeitet > wahrscheinlich dezimal. Hat's ja nicht eilig. Nö, der rundet einfach nur 9-er Perioden. Beim Keil Compiler gibts dafür floatfuzzy: http://www.keil.com/support/docs/1415.htm Peter
Ernst Bachmann wrote: > Manche Programmiersprachen (z.B. SML) bringen deswegen erst garkeinen > Gleichheitsoperator für floats/double mit, um solche Fehler zu > vermeiden. Bestimmte Gleichheits-Tests sind ja in C definiert, beispielsweise lässt sich eine 0 immer exakt darstellen und damit auch vergleichen.
Jörg Wunsch wrote: > Bestimmte Gleichheits-Tests sind ja in C definiert, beispielsweise > lässt sich eine 0 immer exakt darstellen und damit auch vergleichen. Klar, C stellt (wie die meisten anderen Sprachen) einfach einen Gleichheitsoperator für floats zur Verfügung, und baut darauf, dass dem Programmierer schon klar ist das der eine recht wacklige Sache ist. SML kommt mehr aus der Mathematik/Theoretischen Informatik (lambda-Kalkül, etc), da haben die den weggelassen, weil er eben nicht "mathematisch korrekt" funktioniert. Lustigerweise kann man auch unter SML das verhalten des C ==-Operators nachbauen, einfach mit Konstrukten wie !((a<b) || (b<a)) ;) /Ernst
Ich wollte darauf hinaus, dass C für bestimmte Gleitkommazahlen den Test auf Gleichheit garantiert, dafür ist er dann eben nicht ,,wackelig'' -- aber für alle anderen ist er es.
Für bestimmte Zahlen schon. Allerdings garantiert C nicht, dass bei einer Berechnung auch wirklich diese bestimmten Zahlen rauskommen. Wenn ich 1/10*10-1 rechne, muss dabei nicht unbedingt 0 rauskommen.
Rolf Magnus wrote: > Wenn > ich 1/10*10-1 rechne, muss dabei nicht unbedingt 0 rauskommen. Das ist richtig. Allerdings kann ich eine explizit (als Konstante) zugewiesene oder initialisierte 0 als Vergleichswert benutzen, bspw. um festzustellen, ob bereits ein anderer Wert eingetragen worden ist. Ohne Nachzugucken würde ich sagen, dass mindestens noch +Inf und -Inf exakt vergleichbar sind.
Die Vergleiche sind natürlich in C immer richtig! Auch für float/double. Die Schwierigkeit kommt, wie oben schon gesagt, durch die begrenzte Genauigkeit der Darstellung im Rechner. Es stehen eben nur eine begrenzte Anzahl bits zur Verfügung. Somit macht C bei den Tests keine Fehler. Bei Fließkommaberechnungen zwei Zahlen auf Gleichheit testen geht stets per: fabs(a-b) < eps. eps ist dabei die betragsmäßig kleinste darstellbare Fließkommazahl. eps ist definiert als FLT_EPSILON bzw. DBL_EPSILON in float.h
> eps ist definiert als FLT_EPSILON bzw. DBL_EPSILON in float.h
Da musst du vorsichtig sein.
Diese XXX_EPSILON geben nur an, wieviel man zu eine
XXX 0 addieren muss, damit sich auch tatsächlich die
Bitdarstellung ändert. Es ist also die kleinste Zahl
die noch von 0 unterschieden werden kann.
Für Vergleiche, wie vorgeführt, ist das aber normalerweise
nicht geeignet. Wie gross dieses Epsilon sein muss, kann, darf
hängt unter anderem auch von der Vorgeschichte der Zahlen
ab. Also: woher kommen sie? welche Berechnungen mussten gemacht
werden um die zu vergleichenden Zahlen zu erhalten?
Danach richtet sich die Größe des zu verwendenden Epsilons.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.