Floats vergleichen

#451007
Lesenswert?

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
Gast #451008
Lesenswert?

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 + ...
Gast #451009
Lesenswert?

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;
}
#451251
Lesenswert?

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
Gast #451399
Lesenswert?

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.
Moderator Persönliche Seite #451419
Lesenswert?

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.
#452106
Lesenswert?

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
#452269
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren