`return fabs(a - b) < EPSILON;
Das ist in Ordnung, wenn:
- die Größenordnung Ihrer Eingaben ändert sich nicht wesentlich
- sehr kleine Zahlen mit entgegengesetzten Vorzeichen können als gleich behandelt werden
Aber andernfalls wird es zu Problemen führen. Doppelt genaue Zahlen haben eine Auflösung von etwa 16 Dezimalstellen. Wenn die beiden Zahlen, die Sie vergleichen, größer sind als EPSILON*1.0E16, dann könnten Sie genauso gut sagen:
return a==b;
Ich werde einen anderen Ansatz untersuchen, bei dem davon ausgegangen wird, dass Sie sich um das erste Problem kümmern müssen und dass das zweite Problem für Ihre Anwendung in Ordnung ist. Eine Lösung wäre etwa so:
#define VERYSMALL (1.0E-150)
#define EPSILON (1.0E-8)
bool AreSame(double a, double b)
{
double absDiff = fabs(a - b);
if (absDiff < VERYSMALL)
{
return true;
}
double maxAbs = max(fabs(a) - fabs(b));
return (absDiff/maxAbs) < EPSILON;
}
Das ist zwar rechenintensiv, aber manchmal ist es genau das Richtige. In meinem Unternehmen müssen wir so vorgehen, weil wir mit einer technischen Bibliothek arbeiten und die Eingaben um einige Dutzend Größenordnungen variieren können.
Wie auch immer, der Punkt ist folgender (und gilt für praktisch jedes Programmierproblem): Überlegen Sie, was Sie brauchen, und entwickeln Sie dann eine Lösung, die Ihren Bedürfnissen entspricht - gehen Sie nicht davon aus, dass die einfache Lösung Ihren Bedürfnissen entspricht. Wenn Sie nach Ihrer Evaluierung feststellen, dass fabs(a-b) < EPSILON
reicht aus, perfekt - nutzen Sie es! Aber seien Sie sich seiner Unzulänglichkeiten und anderer möglicher Lösungen bewusst.