double vergleichen: Wie lange reicht ==-operator aus?



  • DoppelterSpass schrieb:

    Oder sehe ich das falsch?

    Ja, siehe:

    #include <iostream>
    #include <iomanip>
    
    using namespace std;
    
    int main()
    {
       double wert = 130.2;
       double andererWert = 129.2;
    
       for(int i = 0; i < 10; ++i)
          andererWert += 0.1;
    
       cout << "wert        ======> " << wert << '\n';
       cout << "andererWert ======> " << andererWert << '\n';
    
       if(wert == andererWert)
          cout << "\nwert ist gleich andererWert\n";
       else
          cout << "\nwert ist ungleich andererWert\n";
    
       cout << setprecision(20) << "\nwert        ======> " << wert << '\n';
       cout << "andererWert ======> " << andererWert << '\n';
    }
    

  • Mod

    TNA schrieb:

    Das führt dann zu Phänomenen wie z.B. das eine Variable der ich irgendwann exakt 0.3 zugewiesen habe später bei einem Vergleich mit 0.3 nicht mehr true liefert.

    Das ist unmöglich (wenn wir mal Nicht-Standardumgebungen ignorieren). Einfache Zuweisung verändert niemals den Wert von Zahlen. Ungenauigkeiten ergeben sich genau dann, wenn das exakte Ergebnis einer Operation nicht exakt im Zieltyp dargestellt werden kann, also
    - bei Ergebnissen von Rechenoperationen (z.B. überschüssige Stellen bei der Multiplikation, Werte von Literalen wie 0.3 u.ä.),
    - ein Wert eines Typs in einen eines Typs mit kleinerem Wertebereich/Genauigkeit konvertiert werden muss (double->float u.ä.)



  • Das ist doch genau bei 0,3 der Fall. 0,3 ist als Fließkommazahl nie exakt 0,3 und die Anzahl der Stellen kann eben variieren. Datentypen garantieren immer nur eine Mindestgenauigkeit währen intern manchmal genauer gerechnet wird. Die Repräsentation von "0,3" im Hauptspeicher muss nicht gleich der Repräsentation von 0,3 in einem Register oder Direktoperand sein.



  • camper schrieb:

    TNA schrieb:

    Das führt dann zu Phänomenen wie z.B. das eine Variable der ich irgendwann exakt 0.3 zugewiesen habe später bei einem Vergleich mit 0.3 nicht mehr true liefert.

    Das ist unmöglich

    Genau bei float ist es eben doch möglich (wie du selber schreibst).

    float f=0.3; // int f=0.3; ist das gleiche Phänomen leichter verständlich
    assert(f!=0.3);
    

    Nur bei double (und vermutlich long double) ist es nicht mehr möglich, weil das Literal 0.3 immer als double dargestellt wird.



  • Es reicht solange bis man damit auf die Nase fällt 😃

    Beschäftige Dich mal ein bisschen damit wie Dein Rechner die Zahlen intern verarbeitet. Du wirst schnell sehen, dass es simple Zahlen gibt die überhaupt nicht exakt darstellbar sind z.B. 0.1

    Mit dem Wissen wirst Du dann NIE wieder auf die Idee kommen Fließkommazahlen per == zu vergleichen.

    if ( ( 0.1 + 0.1 ) == 0.2 ) wird nie wahr sein. 😃



  • MichelRT schrieb:

    if (0.1+0.1==0.2) wird nie wahr sein. 😃

    Sag niemals nie.
    Auf meinem Rechnner ist das gerade das Gegenteil der Fall 😃


  • Mod

    weallfloat schrieb:

    camper schrieb:

    TNA schrieb:

    Das führt dann zu Phänomenen wie z.B. das eine Variable der ich irgendwann exakt 0.3 zugewiesen habe später bei einem Vergleich mit 0.3 nicht mehr true liefert.

    Das ist unmöglich

    Genau bei float ist es eben doch möglich (wie du selber schreibst).

    float f=0.3; // int f=0.3; ist das gleiche Phänomen leichter verständlich
    assert(f!=0.3);
    

    Nur bei double (und vermutlich long double) ist es nicht mehr möglich, weil das Literal 0.3 immer als double dargestellt wird.

    Da musst du aber auch korrekterweise mit 0.3f vergleichen. Und das sollte dann auch erfolgreich sein.



  • SeppJ schrieb:

    weallfloat schrieb:

    camper schrieb:

    TNA schrieb:

    Das führt dann zu Phänomenen wie z.B. das eine Variable der ich irgendwann exakt 0.3 zugewiesen habe später bei einem Vergleich mit 0.3 nicht mehr true liefert.

    Das ist unmöglich

    Genau bei float ist es eben doch möglich (wie du selber schreibst).

    float f=0.3; // int f=0.3; ist das gleiche Phänomen leichter verständlich
    assert(f!=0.3);
    

    Nur bei double (und vermutlich long double) ist es nicht mehr möglich, weil das Literal 0.3 immer als double dargestellt wird.

    Da musst du aber auch korrekterweise mit 0.3f vergleichen. Und das sollte dann auch erfolgreich sein.

    Es ging um eine wörtliche Umsetzung des Zitats.
    Selbst float f=0.3;assert(f==0.3f); (wörtliche Umsetzung deiner Aussage) ist implementation-defined.


  • Mod

    weallfloat schrieb:

    Selbst float f=0.3;assert(f==0.3f); (wörtliche Umsetzung deiner Aussage) ist implementation-defined.

    Ich wette, ich kann die benutzte Implementierung erraten. Beim ersten Versuch. Auf egal welchem System.


  • Mod

    weallfloat schrieb:

    Selbst float f=0.3;assert(f==0.3f); (wörtliche Umsetzung deiner Aussage) ist implementation-defined.

    Wenn man annimmt, dass die Wahl in 2.14.4/2 nicht mit der in 4.8/1 übereinstimmen muss. Ansonsten eben

    float f=0.3;assert(f==float(0.3));
    

    Das unmmöglich bezog sich vor allem auf den Fakt, dass

    eine Variable ... exakt 0.3 zugewiesen

    unmöglich ist. Da 0.3 mit den Standardtypen nicht exakt darstellbar ist, kann es logischerweise auch nicht exakt der Wert sein, der in der Variablen gespeichert wird.


Anmelden zum Antworten