671 Stimmen

Welches ist die effektivste Methode für einen Float- und Double-Vergleich?

Was wäre der effizienteste Weg, um zwei double oder zwei float Werte?

Dies einfach zu tun, ist nicht korrekt:

bool CompareDoubles1 (double A, double B)
{
   return A == B;
}

Aber so etwas wie:

bool CompareDoubles2 (double A, double B) 
{
   diff = A - B;
   return (diff < EPSILON) && (-diff < EPSILON);
}

Das scheint eine Verschwendung von Bearbeitungszeit zu sein.

Kennt jemand einen intelligenteren Float-Vergleicher?

-3voto

derke Punkte 439

Wie wäre es damit?

template<typename T>
bool FloatingPointEqual( T a, T b ) { return !(a < b) && !(b < a); }

Ich habe schon verschiedene Ansätze gesehen - aber noch nie diesen, also bin ich auch auf Kommentare gespannt!

-3voto

Oleksandr Boiko Punkte 125

EDIT: In dieser Version wird überprüft, dass die Zahlen nicht mehr als einen Bruchteil (z.B. 0,0001%) voneinander abweichen:

bool floatApproximatelyEquals(const float a, const float b) {
    if (b == 0.) return a == 0.; // preventing division by zero
    return abs(1. - a / b) < 1e-6;
}

Bitte beachten Sie Sneftel die Bemerkung über mögliche Fraktionsgrenzen für Float.

Beachten Sie auch, dass es sich von der Herangehensweise mit absoluten Epsilons unterscheidet - hier kümmert man sich nicht um "Größenordnungen" - die Zahlen könnten z.B. sein 1e100 o 1e-100 werden sie immer einheitlich verglichen, und Sie müssen epsilon nicht in jedem Fall aktualisieren.


Alte Antwort: Auf folgende Weise vergleichen Sie die systemabhängige "String-Darstellung" von zwei Werten (in Ihrem Fall Floats). Ähnlich, wie wenn Sie beide ausdrucken und mit Ihren Augen sehen, ob sie gleich aussehen:

#include <iostream>
#include <string>

bool floatApproximatelyEquals(const float a, const float b) {
    return std::to_string(a) == std::to_string(b);
}

Proc:

  • Der Zahlenfaktor (oder die Potenz) wird effektiv berücksichtigt, so dass es keine Rolle spielt, ob die Zahlen 1,2 oder 1,2e345678 oder 0,00000123 oder 1,2e-345678 sind (das Problem, das normalerweise bei absoluten Epsilons auftritt).

Nachteile:

  • Sie haben keine Kontrolle über die Genauigkeit, mit der Sie Zahlen "runden". Auf meinem System sind es z. B. 6 Stellen nach der ersten signifikanten Stelle (nicht Null) in der Dezimaldarstellung der Zahl (was für die meisten meiner Fälle ausreicht)

-5voto

Warum nicht bitweise XOR durchführen? Zwei Gleitkommazahlen sind gleich, wenn ihre entsprechenden Bits gleich sind. Ich denke, die Entscheidung, die Bits des Exponenten vor die Mantisse zu setzen, wurde getroffen, um den Vergleich zweier Gleitkommazahlen zu beschleunigen. Ich glaube, dass viele Antworten hier den Sinn des Epsilon-Vergleichs nicht verstehen. Der Epsilon-Wert hängt nur davon ab, mit welcher Genauigkeit Fließkommazahlen verglichen werden. Wenn man zum Beispiel mit Fließkommazahlen rechnet, erhält man zwei Zahlen: 2,5642943554342 und 2,5642943554345. Sie sind nicht gleich, aber für die Lösung sind nur 3 Dezimalstellen wichtig, also sind sie gleich: 2,564 und 2,564. In diesem Fall wählen Sie Epsilon gleich 0,001. Ein Epsilon-Vergleich ist auch mit bitweisem XOR möglich. Korrigieren Sie mich, wenn ich falsch liege.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X