Suche gute fuzzyCompare funktion



  • Hallo liebe Forengemeinde,

    ich suche eine Funktion, die zwei floats miteinander vergleicht. Dabei gelten zwei floats als gleich, wenn sie in den ersten Nachkommastellen übereinstimmen. Die genaue Anzahl an Nachkommastellen, die übereinstimmen sollen, kenn ich nicht. Ich vertraue da euren Empfehlungen.
    Eine solche Funktion gibt es zB in der Qt Bibliothek als qFuzzyCompare. Leider haben sie den Quelltext rausgenommen.
    Wäre echt nett, wenn jmd. kurz eine solche Funktion hier posten könnte, falls einer das schon iwo zu liegen hat.

    Danke im voraus 👍


  • Mod

    Gut sei mal dahin gestellt, ist das erste was mir dazu eingefallen ist und erfüllt seinen Zweck ungefähr:

    #include <cmath>
    
    bool fuzzy_compare(double lhs, double rhs, unsigned N=8)
    {
      if (std::fabs(rhs - lhs) < lhs/std::pow(10,N))
        return true;
      else 
        return false;
    }
    
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
      cout << fuzzy_compare(1.23456789, 1.23456788) << '\n'
           << fuzzy_compare(1.23456789, 1.23457788) << '\n'
           << fuzzy_compare(123456789, 123456788) << '\n'
           << fuzzy_compare(-123456789, -123457788) << '\n'
           << fuzzy_compare(123456789, 123456788, 10) << '\n'
           << fuzzy_compare(123456789, 123457788, 4) << '\n'
           << fuzzy_compare(-0.000001234, -0.000001233) << '\n'
           << fuzzy_compare(0.000012345, 0.000012344,3) << '\n';
    }
    


  • Was heißt denn Qt hat den Quelltext rausgenommen? Auf deren Seite find ich immer noch nen source download.

    Edit: Schau mal was ich gefunden hab:

    static inline bool qFuzzyCompare(double p1, double p2)
    {
        return (qAbs(p1 - p2) <= 0.000000000001 * qMin(qAbs(p1), qAbs(p2)));
    }
    
    static inline bool qFuzzyCompare(float p1, float p2)
    {
        return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2)));
    }
    

    qAbs/qMin dann einfach durch std:: sachen ersetzen, oder wenn du willst such ich dir den code dazu auch raus.

    Edit2:

    template <typename T>
    inline const T &qMin(const T &a, const T &b) { if (a < b) return a; return b; }
    
    template <typename T>
    inline T qAbs(const T &t) { return t >= 0 ? t : -t; }
    

    Stand: 4.7.3 (4.7.4 gibts glaub ich schon, glaube aber nicht, dass es da nennenswerte änderungen gibt).



  • Ok vielen Dank für die schnelle und großartige Hilfe!
    Ich muss zu meiner Schande gestehen, dass ich wohl in den falschen Dateien gesucht habe. Habe nämlich den SDK Ordner auf meinem PC durchsucht und nur eine gekürzte Fassung oder derartiges gefunden. Aber nun habe ich ja eine gute Lösung von euch!



  • SeppJ schrieb:

    #include <cmath>
    
    bool fuzzy_compare(double lhs, double rhs, unsigned N=8)
    {
      if (std::fabs(rhs - lhs) < lhs/std::pow(10,N))
        return true;
      else 
        return false;
    }
    

    Warum überprüfst du einen bool um ihm dann das Ergebnis des if zuzuweisen? 🙄

    bool fuzzy_compare(double lhs, double rhs, unsigned N=8)
    {
      return (std::fabs(rhs - lhs) < lhs/std::pow(10,N));
    }
    

    😉



  • BootLag-BootLag- schrieb:

    Dabei gelten zwei floats als gleich, wenn sie in den ersten Nachkommastellen übereinstimmen.

    Also, 99.999 und 100.000 sind total verschieden, ja? :-p

    Vielleicht suchst Du eher so etwas

    abs(x-y) <= 0.01 * max(abs(x),abs(y))
    

    wobei die 0.01 hier so eine Art "relative Unschärfe" wäre.

    BootLag-BootLag- schrieb:

    Die genaue Anzahl an Nachkommastellen, die übereinstimmen sollen, kenn ich nicht. Ich vertraue da euren Empfehlungen.

    Janz falscher Ansatz; denn das kommt sehr stark drauf an, was Du da eigentlich berechnest. Siehe Artikel Numerische Auslöschung.


  • Mod

    krümelkacker schrieb:

    BootLag-BootLag- schrieb:

    Dabei gelten zwei floats als gleich, wenn sie in den ersten Nachkommastellen übereinstimmen.

    Also, 99.999 und 100.000 sind total verschieden, ja? :-p

    Heh, meine Lösung macht das bewusst richtig und die ziemlich identische Qt-Lösung ebenfalls.


Anmelden zum Antworten