# Wann ist ein == Vergleich bei Gleitkommazahlen fahrlässig?



## gp9WTd (23. Nov 2009)

Hallo!

Der Titel sagt bereits alles, aber ich möchte hier nun doch nochmal genauer erläutern.

Ist es nicht so, dass es höchst fahrlässig ist, 2 Gleitkommazahlen mit dem == Operator auf Gleichheit zu überprüfen, selbst wenn diese Zahlen eigentlich indentisch sein müssten? Wegen der Ungenauigkeit vermute ich mal. Okay, man kann das ganze dann mit einem Epsilon lösen, das ist mir bereits bekannt.
Aber gibt es auch Fälle, wo ein == doch zulässig ist?

Ich denke das hängt davon ab, wo die Zahlen herstammen.

Was wäre mit:

float a = 0;
float b = 0;

if( a == b)...


Kann das hier auch schon Probleme machen, oder ist das sicher?


In meinem speziellen Fall kommt die Zahl aus einem Swing-Fenster und wird nach double geparst, anschließend im Code dann mit einer Hardcoded 0 verglichen. In ein paar Testläufen gabs keine Probleme - kann ich davon ausgehen dass das passt, oder sollte doch lieber Epsilon zum Zuge kommen? Wenn der User 0 eingibt, soll die Bedingung eben true werden.


Kurz gesagt wollte ich wissen, wann gibts Probleme, wann nicht.


Danke!


----------



## javimka (23. Nov 2009)

Wenn die Bitfolgen übereinstimmen, dann stimmt auch der == Vergelich. Bei einer klaren 0 ist das auf jeden Fall so. Ich glaube, -0 und 0 werden auch als gleich aufgefasst.


----------



## Ark (23. Nov 2009)

Ich denke mal, der Parser wird dir keine gesetzten Bits hinzudichten, wenn der Nutzer genau 0 eingibt. Insofern sollte das mit Test auf Gleichheit passen.

Ark


----------



## Marco13 (23. Nov 2009)

Ja, es ist ein bißchen heikel... Man könnte sagen: Wenn 
- der Wert exakt darstellbar ist UND
- der Wert nicht ausgerechnet, sondern _gesetzt_ wird
ist ein ==-Vergleich OK. Wenn man in einer Klasse z.B. eine private float-Variable von 0 nach 1 und wieder von 1 nach 0 interpoliert (und am Ende die Werte explizit setzt) dann kann man mit if(x==0) oder if(x==1) abfragen, an welchem Ende man gerade ist...


----------



## T0ken (23. Nov 2009)

Höre das ganze zum ersten mal...

Hab kurz was zusammengeschrieben und sehe das Problem nicht -

Ist das überhaupt ein praxisrelevantes Programm oder eher was auf theoretischer Meta-Ebene? ???:L


```
public class Test {
  public static void main(String[] args) {
    double d1 = 0.3;
    double d2 = 0.3;
    
    if ( d1 == d2 ) {
      System.out.println("gleich");
    }
    else {
      System.out.println("nicht gleich");
    }
  }
}
```

Ausgabe: "*gleich*"

Bei primitiven Datentypen, zu denen *double* und* float* gehören, funktioniert das doch problemlos? :bahnhof:


----------



## Ark (23. Nov 2009)

Füg mal so was wie

```
d1 *= 10;
d1 += 0.1;
d1 /= 10;
d1 -= 0.01;
```
ein. Es sollte mich wundern, wenn es dann noch auf gleich rauskommt.

Ark


----------



## hdi (23. Nov 2009)

Evtl lieber Double.equals() nutzen? Vllt ist das ja dort gut gelöst. Wobei ich auch schon gehört hab dass Java in der Math-API ein paar Bugs drinnen hat.


----------



## javimka (23. Nov 2009)

Sieht nicht so aus.

```
public class Double {

    public boolean equals(Object obj) {
	return (obj instanceof Double)
	       && (doubleToLongBits(((Double)obj).value) ==
		      doubleToLongBits(value));
    }

    public static long doubleToLongBits(double value) {
	long result = doubleToRawLongBits(value); // native Methode
	// Check for NaN based on values of bit fields, maximum
	// exponent and nonzero significand.
	if ( ((result & DoubleConsts.EXP_BIT_MASK) == 
	      DoubleConsts.EXP_BIT_MASK) &&
	     (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
	    result = 0x7ff8000000000000L;
	return result;
    }
}

EXP_BIT_MASK	= 0x7FF0000000000000L;
SIGNIF_BIT_MASK	= 0x000FFFFFFFFFFFFFL;
```


----------



## Marco13 (23. Nov 2009)

@T0ken:

```
double d1 = 3 * 0.1;
    double d2 = 0.9 / 3;
```
reicht schon...


----------

