[cast float->double] definiertes verhalten?



  • naja, also gott sei dank arbeiten sie mit einer Genauigkeit von N, wäre sonst auch sehr traurig. Und das man zwei Fließkomma-Zahlen nur im Epsilon-Bereich auf Gleichheit prüft ist mir ebenfalls bekannt.

    ABER:

    float  a = 0.1;
    double b = 0.1;
    bool erg = std::fabs( (double)a-b )>1.E-10;
    
    //Windows + cl:
    -> erg=false;
    //Linux gcc
    -> erg=true;
    

    Jetzt einmal ungeachtet der Tatsache, dass immer den genaueren Tyoen auf den "ungenaueren" casten sollte bei einem solchen Vergleich, kommt eben compiler Abhängig etwas anderes heraus. Und daher wollte ich wissen, ob das VErhalten irgendwie definiert ist.



  • Da fuer die groessen der einzelnen Fliesskommatypen nur Mindestwerte vorgegeben sind, aber keine fest definierten Wertebereiche, kann das Verhalten nicht definiert sein. Auf einer Plattform wo float und double die gleiche Anzahl bytes haben wird die Differenz zwischen a und b immer 0 sein. Bei allen anderen Plattformen ist das Verhalten davon abhaengig, wie gross der Unterschied in der Genauigkeit von float und double ist, und wie genau 1E-10 dargestellt werden kann.

    Lass dir doch mal auf den verschiedenen Compilern und Plattformen ein sizeof(float) und sizeof(double) ausgeben.



  • also auf beiden Plattformen besitzen float und double ihre standardgroesse von 4 bzw. 8 byte



  • Da steht nicht irgendwas beliebiges im neu hinzugekommenen bereich, sondern das gleiche.

    Gib einfach mal dein float mit der gleichen Anzahl an Nachkommastellen aus.



  • Da wird wahrscheinlich einfach die Mantisse mit Nullen aufgefüllt. Binär natürlich, im Dezimalsystem ergibt das irgendwelche beliebig aussehenden Ziffern.



  • Ponto schrieb:

    Da steht nicht irgendwas beliebiges im neu hinzugekommenen bereich, sondern das gleiche.

    Gib einfach mal dein float mit der gleichen Anzahl an Nachkommastellen aus.

    wenn dort das gleiche stehen würde, dann würde des eps-test in beiden fällen funktionieren 😉



  • Da ich deinen Code nicht kenne, kann ich nicht sagen, was du falsch machst. Aber probiere einfach den folgenden Code aus:

    #include <iostream>
    
    int main() {
    
       double a = 0.01;
       float  b = 0.01;
       double c = b;
    
       std::cout.setf(std::ios::fixed); 
       std::cout.precision(10);
       std::cout << "Precision 10 double:    " << a << std::endl;
       std::cout << "Precision 10 float:     " << b << std::endl;
       std::cout << "Precision 10 assigned:  " << c << std::endl;
       std::cout.precision(20);
       std::cout << "Precision 20 double:    " << a << std::endl;
       std::cout << "Precision 20 float:     " << b << std::endl;
       std::cout << "Precision 20 assigned:  " << c << std::endl;
    }
    

    Du siehst, dass die Zuweisung eines float zu einem double den Wert überhaupt nicht ändert (Zumindest auf gängigen Platformen). Das ist auch ganz klar. Die zusätzlichen Bits der Mantisse eines double werden mit Nullen aufgefüllt und Nullen verändern den Wert nicht.

    Du siehst die unterschiedlichen Werte nur deshalb, weil du bei beiden Ausgaben nicht die gleiche Präzision verwendet hast.

    Das ist übrigends die Ausgabe auf meinem Rechner:

    ponto@burns:~/Savage2> ./a.out
    Precision 10 double:    0.0100000000
    Precision 10 float:     0.0099999998
    Precision 10 assigned:  0.0099999998
    Precision 20 double:    0.01000000000000000021
    Precision 20 float:     0.00999999977648258209
    Precision 20 assigned:  0.00999999977648258209
    


  • Wenn du die Ausgabe noch länger machst, dann siehst du, dass der GENAUE Wert, den die float Variante von 0.1 hat, dieser ist:

    0.00999999977648258209228515625



  • Du koenntest dir den float und den double byte-weise in hexadezimal-Darstellung ausgeben lassen. Dann kannst du exakt vergleichen, was die Compiler unterschiedlich machen.



  • okay, das beispiel von Punto reicht mir vollkommen. genau so sieht es bei mir eigentlich auch aus. und letztlich ist es auch s wie ich es mir gedacht habe. mus snochmal testen wieso der Vergleich beim gcc dann hingehauen hat, da ich exakt die gleichen Werte erhalte wie Punto...


Anmelden zum Antworten