2013-03-22 12 views
15

Was ist eine elegante, lesbare und nicht-verbose Art des Vergleichens zweier Gleitkommazahl für exakte Gleichheit?Überprüfen Sie zwei float/double-Werte für exakte Gleichheit

So einfach es klingen mag, es ist ein böses Problem. Der == Operator wird nicht den Job für NaN getan und hat auch eine besondere Behandlung für Null:

(+0.0 == -0.0) -> true 
Double.NaN == Double.NaN -> false 

Aber ich will, um zu bestimmen, ob zwei Werte sind genau die gleichen (aber ich nicht Pflege für verschiedene NaN Muster, also jedes NaN == irgendein anderes NaN -> wahr).

ich kann tut dies mit diesem hässlichen Monster Stück Code:

Double.doubleToLongBits(a) == Double.doubleToLongBits(b) 

Gibt es einen besseren Weg, dies zu schreiben (und die Absicht offensichtlich zu machen)?

+0

Sie nicht Tag, warum Sie dies tun möchten. Wenn sie wirklich Gleitkommazahlen sind, wird Ihre Antwort nicht sinnvoll sein. – Julian

+0

@Julian Siehe PeterLawreys Antwort für ein Beispiel, wo es sehr bedeutungsvoll ist. Meine Anwendung ist jedoch die equals() -Methode eines Objekts, wo ein float Teil des Primärschlüssels ist (nicht nach meiner Wahl). Der Gleitkomma-Wert widerspricht gewöhnlich intuitiven Annahmen, weshalb ich darauf achten muss, dass die Randfälle abgedeckt werden. – Durandal

+0

Sorry, du könntest es nicht besser machen, dein "hässliches Monsterstück" ist schon perfekt ... –

Antwort

10

Was Sie haben, ist bereits der beste Weg, es zu tun, würde ich sagen. Es macht deutlich, dass Sie an der bitweisen Darstellung des Wertes interessiert sind. Sie konvertieren diese Bits in long als einen bequemen 64-Bit-Typ, der kein funky Verhalten hat.

Wenn Sie nicht wollen, es häufig in Ihrem Code-Basis erscheint, fügen Sie einfach eine Methode, es zu wickeln:

public static boolean bitwiseEqualsWithCanonicalNaN(double x, double y) { 
    return Double.doubleToLongBits(x) == Double.doubleToLongBits(y); 
} 

Beachten Sie, dass nach Ihrer Frage, tut dies nicht differenzierbare zwischen verschiedenen NaN-Werten. Wenn Sie dies zu einem späteren Zeitpunkt tun möchten, müssen Sie Double.toRawLongBits verwenden.

+0

Mhhh, sowohl Ihre als auch Peters Antwort haben ihren Reiz. Der besseren Übersicht halber denke ich, dass der statische Helfer ein wenig besser ist, da ich mich einfach zu der Methode äußern kann und jeder, der über den Anruf stolpert, wird dort ankommen. Immer noch über einen guten Methodennamen nachgedacht. – Durandal

22

können Sie verwenden

Double.compare(a, b) == 0 

Vom javadoc für compareTo

  • Double.NaN nach dieser Methode angesehen wird sich gleich und größer als alle anderen Doppelwerte (einschließlich Double.POSITIVE_INFINITY).
  • 0,0d wird bei dieser Methode als größer als -0,0d angesehen.
+0

Wird das zwischen den beiden 0 auch richtig unterscheiden? –

+0

Es wird NaNs tun. Überprüfung auf -0 und 0 –

+1

Ich habe gerade überprüft. Es tut. Nett - wenn auch nicht * offensichtlich * richtig, würde ich sagen. (Ich hätte intuitiv * erwartet *, dass positive und negative Null gleich sind. Ich bevorzuge den Code, der es auffällig macht, dass du an den genauen Bits interessiert bist.) –

Verwandte Themen