floats richtig vergleichen
-
poc|off schrieb:
Kann man denn irgendwie feststellen, ob die Differenz zweier Gleitkommazahlen größer ist als die kleinstmögliche Differenz zwischen beiden?
Das ergibt irgendwie keinen Sinn, da sollte ich nochmal drüber nachdenken.:)
-
Nexus schrieb:
std::numeric_limits<>::epsilon()hilft dir da eigentlich nicht viel, da es nur die kleinste mögliche Inkrementierung von 1. angibt.Und gibt es eine Möglichkeit, die kleinste mögliche Inkrementierung einer beliebigen Gleitkommazahl zu bestimmen?
-
Gleitkommazahlen fragt man auf Gleichheit immer auf den Absultwert (fabs) der Differenz der beiden Werte auf kleiner eines Toleranzwertes (z.B. eps=0.1e-5) ab.
-
nimm halt:
const float dein_toleranzwert_fuer_1x1 = 0.00001f; bool IsSame (float a, float b, float coord_x, float coord_y) { a -= b; b = dein_toleranzwert_fuer_1x1 * sqrt(coord_x * coord_y); if (a < 0) return a >= -b; return a <= b; }bb
-
unskilled schrieb:
nimm halt:
const float dein_toleranzwert_fuer_1x1 = 0.00001f; [...]Ich verstehe die Intention dahinter, aber wie kommst du auf die 0.00001?
-
ich würde das als templatze machen:
template<T> static T getTolerance( T dummy ) { return T(0); }und dann ein paar spezialisierungen anlegen:
template<> static double getTolerance( double dummy ) { return .000001; } template<> static float getTolerance( float dummy ) { return .0001f; }bin mir grad nicht sicher, ob die syntayx bei den spezialisierungen korrekt sind, aber ihr wisst was gemeint ist.
Eventuell kann man das epsilon auch abhängigmachen, von der größe von dummy, da ja die genauigkeit bei großen zahlen abnimmt
-
berniebutt schrieb:
Gleitkommazahlen fragt man auf Gleichheit immer auf den Absultwert (fabs) der Differenz der beiden Werte auf kleiner eines Toleranzwertes (z.B. eps=0.1e-5) ab.
Na hoffentlich nicht.
http://c-faq.com/fp/fpequal.html
-
Beachten muss man auch noch den Fall, dass die zwei Achsen unterschiedliche Auflösungen haben und man je nach Achse verschiedene Epsilons braucht. Evtl kann man den Vergleich auch an das Koordinatensystem oder die Achsen weiter-dirigieren, um nicht jedesmal die Auflösung übergeben zu müssen?
-
Habe etwas gefunden: http://www.cygnus-software.com/papers/comparingfloats/Comparing floating point numbers.htm#_Toc135149455
Das scheint zu tun, was ich will.
-
unräg schrieb:
berniebutt schrieb:
Gleitkommazahlen fragt man auf Gleichheit immer auf den Absultwert (fabs) der Differenz der beiden Werte auf kleiner eines Toleranzwertes (z.B. eps=0.1e-5) ab.
Na hoffentlich nicht.
http://c-faq.com/fp/fpequal.htmldouble d1=7.500000002; double d2=15.00000002; double dx; double eps=1.e-6; int gleich; dx=fabsl(d1-d2/2.0); if(dx < eps) gleich=TRUE; else gleich=FALSE;Was soll an dieser alt bewährten Vorgehensweise zum Prüfen zweier Gleitkommanzahlen auf Gleichheit etwas anders oder besser gemacht werden? So jedenfalls geht es klar und übersichtlich für alle Compiler und ist eine gängige Praxis, vor allem bei Iterationen. Der WEB-Hinweis sagt auch nichts anderes!
-
berniebutt schrieb:
Was soll an dieser alt bewährten Vorgehensweise zum Prüfen zweier Gleitkommanzahlen auf Gleichheit etwas anders oder besser gemacht werden?
Das Problem kommt dann, wenn du mit sehr großen oder sehr kleinen Zahlen operierst. Wenn du auf Zahlen bei 1.e-7 opererierst, sind sie nach dem "Standard-Algorithmus" immer gleich - was ja wohl kaum gewollt sein kann. Und bei sehr großen Zahlen hast du praktisch nie "Gleichheit", auch wenn es eigentlich so sein sollte. Deshalb ist die Lösung aus dem cygnus-software-Link so interessant, weil es die Problematik eben löst.