Sehr kleine double-Werte nahe 0 mit < Operator vergleichen gibt falsche Ergebnisse



  • Die definitelyLessThan-Relation wird von Knuth in TAOCP, Band 2 in Sektion 4.2.2 definiert, und Transitivität geht dabei in der Tat verloren. Allerdings sind die knuthschen Relationen in der angegebenen Form auf ieee754-floats nur eingeschränkt anwendbar; durch die Einführung der Sonderwerte inf, -inf und insbesondere NaN gelten einige seiner Definitionen nicht mehr. Zum Beispiel ist

    double x = 0.0 / 0.0; // NaN. Wahlweise 0 * inf, inf - inf, inf/inf o.ä.
    
    if(x == x) {
      puts("Passiert nie.");
    } else {
      puts("Hier landen wir.");
    }
    

    mit knuthschen Floats stumpf nicht möglich.

    Das ist etwas, was man bei der Arbeit mit Fließkommazahlen immer im Hinterkopf behalten sollte: Vergleiche mit NaN sind immer falsch, Berechnungen mit NaN sind immer NaN. !(x < y) bedeutet nicht (y >= x). Wenn man beispielsweise in einem Suchverfahren mit der Schleifenbedingung nicht aufpasst, kann man sich damit schon mal Endlosschleifen einhandeln, die bei seltenen Eingabeparametern auftreten und deshalb sogar durch die Tests rutschen können.

    Es ist allerdings auch etwas, was oft nicht im Hinterkopf behalten wird. Denkt daran, wenn ihr das nächste mal jemanden

    double min(double x, double y) { return x < y ? x : y; }
    

    schreiben seht, und weist ihn dann darauf hin, dass min(x, y) so nicht immer das selbe wie min(y, x) ist.



  • Hier wird etwas durcheinandergeschmissen: Das eigentlich Problem sind nicht die Vergleichoperatoren (natürlich kann ich zwei floats auf Gleicheit prüfen!).
    Das Problem ist das die Eigenschaften der gewohnten arithmetischen Operation +,-,*,/ usw. für reelle Zahlen sich nicht auf die floating-point Zahlen Übertragen.


Anmelden zum Antworten