Über den Unterschied zwischen einem Wert und dem Wert als Variable



  • Ich habe folgendes Programm:

    #include <iostream>
    
    using namespace std;
    
    int main(void)
    {
        double a = 0.6;
        double b = 0.6*20.0;
        if(12.0 == a*20.0)
        {
            cout << "12.0 == " << a*20.0 << endl;
        }    
        else
        {
            cout << "12.0 != " << a*20.0 << endl;
        }
        if(12.0 == b)
        {
            cout << "12.0 == " << b << endl;
        }    
        else
        {
            cout << "12.0 != " << b << endl;
        } 
        cin.get();   
        return (0);
    }
    

    Die Ausgabe sieht folgendermassen aus:

    12.0 != 12
    12.0 == 12

    Aber das würde heißen, dass es einen semantischen Unterschied zwischen dem Wert einer Variablen als Literal (oder als zusammengesetzten Ausdruck) und dem gleichen Wert als Variablen gibt.

    Woran liegt das??

    Felix



  • Hab mir hier deinen Quelltext kopiert und in ein projekt eingefügt. Bei mir kommt 2 mal 12.0 == 12 raus...



  • Mit welchem Compiler hast du das denn kompiliert?

    Mit dem Microsoft Compiler kommt bei mir auch 2 mal 12 == 12 raus

    Aber mit Dev-Cpp bekomme ich 12 != 12 und 12 == 12 als Ausgabe

    😕 😕 Komisch, oder?



  • Jetzt wollt ich euch grad in die FAQ verdammen und find das gar nicht 😮

    Dann sag ich halt: Könnt ihr nicht suchen? 🕶 🤡



  • aber wenn man exakt die gleichen berechnungen macht sollte auch immer das gleiche rauskommen. aber wenn die ergenisse nicht genau sind.



  • Bei mir:

    1. gcc unter Linux, ohne Optimierung:
      12.0 != 12
      12.0 == 12

    2. gcc unter Linux, mit -O:
      12.0 == 12
      12.0 == 12

    Darauf aufbauend folgender Erklärungsansatz:
    Der Compiler kann 0.6*20.0 schon beim Übersetzen berechnen (wie auch immer er das macht), dabei kommt 12.0 heraus. Er weist also b direkt den Wert 12.0 zu. a ist jedoch 0.6, und 0.6 kann im Binärsystem nicht exakt dargestellt werden. Die spätere Multiplikation mit 20.0 ergibt deshalb auch nicht exakt 12.0. Mit Optimierung ist der Compiler ein wenig schlauer, macht eine Datenflussanalyse, und erkennt, dass im Ausdruck 'a*20.0' a immer den Wert 0.6 hat. Deshalb ersetzt er a dort durch 0.6 und berechnet wie oben 0.6*20.0 == 12.0.

    Wie genau er diese Berechnung zur Compilezeit aussführt, weiß ich nicht, aber das ist immerhin schon die halbe Erklärung.



  • a ist jedoch 0.6, und 0.6 kann im Binärsystem nicht exakt dargestellt werden.

    Wieso kann denn 0.6 nicht genau im Binärsystem dargestellt werden??



  • Phoemuex schrieb:

    Wieso kann denn 0.6 nicht genau im Binärsystem dargestellt werden??

    Aus demselben Grund, aus dem 1/3 im Dezimalsystem nicht genau dargestellt werden kann: Es ist ein periodischer "Dual"-bruch. Das gilt für alle Zahlen, bei denen in der Bruchdarstellung der Nenner keine Potenz von 2 ist.



  • hm... man hätte es als bcd darstellen können (also als 0,0110). ist aber wohl nicht praktikabel.



  • BCD-Code find ich bescheuert. Das ist nichts anderes als ne speicherraubende Binärdarstellung. Wenn man bedenkt, dass bei jeder Dezimalstelle sechs darstellbare Zeichen verloren gehen 👎



  • Die Sache mit o.6*20 und einem Vergleich von reellen Zahlen ist ausführlich in dem Buch von May: Grundkurs Software-Entwicklung mit C++ beschrieben. Es hängt mit der internen Zahlendarstellung zusammen, die nur in seltenen Fällen mit den mathematischen Zahlen übereinstimmen. Jedenfalls sollte man nie (!) reelle Zahlen in folgender Weise vergleichen x == 20.0. Auf den Sachverhalt kann ich hier nicht näher eingehen - das wir zu lang - , dort findet ihr aber genügend gute Info und eine Lösung, wie man es richtig macht! Die Unterschiede - mal kommt 12.0 == 12, mal 12 != 12 heraus - dürften von den unterscshiedlichen Compilern herrühren!!
    😋



  • Michael E. schrieb:

    BCD-Code find ich bescheuert. Das ist nichts anderes als ne speicherraubende Binärdarstellung.

    Nö, es ist ne Dezimaldarstellung. Das heißt, du kannst zwar effektiv weniger Zahlen darstellen, aber in manchen Gebieten (Finanzen z.B.) mehr von den interessanten.



  • Wieso sollte BCD da interessanter sein, wenn ich bei den nicht zu verachtenden Speichermengen bei Banken was sparen könnt? Außerdem muss man sich erst nen Interpreter für die Darstellung schreiben. Ich finds unnötig.



  • Michael E. schrieb:

    Wieso sollte BCD da interessanter sein, wenn ich bei den nicht zu verachtenden Speichermengen bei Banken was sparen könnt?

    Weil in Banken ausschließlich mit Dezimalzahlen gearbeitet wird, die im Allgemeinen nicht exakt im Binärsystem repräsentiert werden können. Du handelst dir also unweigerlich Ungenauigkeiten ein, die sich aufschaukeln können.



  • Außerdem unterstützt die FPU das BCD Format und der zusätzliche Speicher ist hier nur nebensächlich, denn eine Bank braucht nunmal sehr exakte Werte.



  • Dann nehm ich halt Integer / irgendeinen Wert, dann ist die Genauigkeit wieder da...


Anmelden zum Antworten