int-Cast nach Rundung zuverlässig?



  • Hallo,
    folgendes beschäftigt mich gerade: Die Rundungsfunktionen floor() und ceil() liefern bekanntlich einen Gleitkommawert zurück. Oft will man aber das Ergebnis als int weiterverarbeiten, schreibt also etwas wie

    int i = (int) floor (x);
    

    Kann es hier eigentlich passieren, dass das "ganzzahlige Gleitkomma-Ergebnis" von floor() nicht exakt als double dargestellt werden kann und der int-cast dann ein um eins vermindertes Ergebnis liefert? Könnte also z.B., wenn floor(x) 7.0 liefert, die 7.0 in Wirklichkeit etwas wie 6.999999999... sein und deshalb der int-Cast 6 liefern? Oder wird das durch Compiler- bzw. Sprachspezifikation bereits berücksichtigt und ausgeschlossen?


  • Mod

    Die gängige Fließkomma-Darstellung IEEE 754 legt fest, dass float alle Ganzzahlen in und inklusive ±(224)\pm (2^{24}) darstellen kann. In diesem Interval wirst du also keine Probleme haben. Sobald du mit Zahlen arbeitest, die sehr groß sind, wird auch die Genauigkeit entsprechend abnehmen, und es hat wenig Zweck, in solchen Größenordnungen über Differenzen von 11 zu sprechen.


  • Mod

    Der Cast an der Stelle ist übrigens vollkommen unnötig.



  • SeppJ schrieb:

    Der Cast an der Stelle ist übrigens vollkommen unnötig.

    Wollte gerade einen dummen Kommentar über Warnungen und so schreiben, hab's dann aber sicherheitshalber nochmals getestet. Und du hast recht. Keiner meiner Compiler gibt dafür eine Warnung aus. Aber wieso nicht? Bei implizitem Narrowing gibt der Compiler doch normalerweise Warnungen aus...



  • SeppJ schrieb:

    Der Cast an der Stelle ist übrigens vollkommen unnötig.

    funktional schon, aber zur Dokumentation hilfreich. Er zeigt, dass hier kein potenzieller Bug versteckt ist, sondern dass sich der Programmierer etwas dabei gedacht hat.

    In diesem Fall ist es ziemlich offensichtlich, aber wenn statt floor jetzt eine Funktion aufgerufen wird, die wiederum floor verwendet, ist das schon nicht mehr auf den ersten Blick erkennbar.



  • SeppJ schrieb:

    Der Cast an der Stelle ist übrigens vollkommen unnötig.

    Unnötig ja, "vollkommen unnötig" nein. So einen Cast explizit nochmal hinzuschreiben dokumentiert immerhin dass dieser beabsichtigt ist.
    Auch wenn da manche Leute eine Krise bekommen, findet man sowas z.B. in meinem Code ziemlich häufig (sogar solche Schätzchen wie 1.0 + static_cast<double>(1) :D).

    Finnegan



  • Finnegan schrieb:

    (sogar solche Schätzchen wie 1.0 + static_cast<double>(1) :D).

    Womit wir wieder bei "vollkommen unnoetig" angelangt waeren 😉



  • Also danke nochmal. Dass alle Ganzzahlen bis ±(224)\pm (2^{24}) von float exakt dargestellt werden, war mir so noch nicht klar.

    BTW: Ich hätte auch schwören können, dass die Zuweisung von float an int ohne Cast eine Warnung auslöst. Aber auch wenn dem nicht so ist, kann die Botschaft "Ich will hier ganz bewusst die Nachkommastellen wegschneiden" an andere Leute, die meinen Code lesen (oder an mich selbst in einem halben Jahr 😉 ), eine sehr Wichtige sein. So ein Cast ist nicht überflüssig, nur weil er "bloß" für den Programmierer da ist.


Anmelden zum Antworten