Problem mit Float-Ungenauigkeit.
-
Ich habe ein Klasse welche diese Eigenschaft besitzt:
class TglObject { protected: GLfloat color[3]; public: GLfloat* getColor() const {return (GLfloat*)color;}; };Im Array ist folgender Wert gespeichert (0.9,0.9,0.9)
In einer Funktion mache ich nun folgendes:
GLfloat col; col = edit->getColor()[0]; if (col == 0.9) edit->setColor(0.5,0.5,0.9); else edit->setColor(0.9,0.9,0.9);Es wird immer nur der else-Zweig betreten, weil col nicht 0.9 sondern 0.89999999 enthält. Wieso? Es wurden überall doch dieselben Typen verwendet.
(GLfloat ist ein float.)
Was muss ich machen, ob sowas zu vermeiden?
-
Anfänger06 schrieb:
Es wird immer nur der else-Zweig betreten, weil col nicht 0.9 sondern 0.89999999 enthält. Wieso?
Weil man Zahlen, die man Dezimal endlich darstellen kann, binär nicht zwangsläufig ebenfalls endlich darstellen kann.
Was muss ich machen, ob sowas zu vermeiden?
Siehe dazu auch hier: http://www.c-plusplus.net/forum/viewtopic-var-t-is-133410.html
Gruß Caipi
-
du kannst floats nicht einfach auf gleichheit prüfen, eben weil sie nicht 1:1 abgespeichert werden können, was du schon festgestellt hast.
also am besten eine art toleranz festlegen:float toleranz = 0.001f; if(col < 0.9f + toleranz && col > 0.9f - toleranz) //...
-
Noch was: Auch setColor() erwartet GLfloats. D.h. überall wird nur mit floats gearbeitet. Nirgendwo tauchen double auf. Solche fehler sind doch aber fehler die beim konvertieren von float zu double passieren, oder?
-
float kann einen Wert nicht exakt speichern, deshalb verwendet er die jeweils nächstgelegene Zahl, die er speichern kann - und deshalb sind Vergleiche in float auch nicht besonders exakt.
Als Lösung kann ich dir nur anbieten, näherungsweise zu vergleichen:
const float EPSILON = 1e-5f; ... if(fabs(col-0.9)<EPSILON) { // col ist ungefähr 0.9 -> rechne damit weiter } else { ... }Edit: Mist - ich werde wohl alt.
-
Anfänger06 schrieb:
Noch was: Auch setColor() erwartet GLfloats. D.h. überall wird nur mit floats gearbeitet. Nirgendwo tauchen double auf. Solche fehler sind doch aber fehler die beim konvertieren von float zu double passieren, oder?
nicht zwangsläufig. fließkommazahlen werden nicht wie gewohnt dezimal abgespeichert, sondern so: http://de.wikipedia.org/wiki/Flie%C3%9Fkomma-Zahlen
-
Anfänger06 schrieb:
Noch was: Auch setColor() erwartet GLfloats. D.h. überall wird nur mit floats gearbeitet. Nirgendwo tauchen double auf. Solche fehler sind doch aber fehler die beim konvertieren von float zu double passieren, oder?
Nein, die Fehler tauchen überall auf, wo du mit Gleitkommazahlen arbeitest - egal ob float, double oder irgendwas anderes.