double rundet automatisch -.-



  • Schlechte Lösung. Nimm dafür die IOStream-Manipulatoren.



  • dot schrieb:

    janmerkschien schrieb:

    weiß jemand wieso das so ist ?

    Wil 9999.99 als double nicht exakt darstellbar ist.

    Aber ausreichend genug. Glaubst du ernsthaft, das double bei zulässigen 6 Stellen schon aufgibt? 9999.99 wird etwa als 9999.9899999999998 gespeichert.



  • janmerkschien schrieb:

    ich habe das problem aber mitlerweile anders gelöst . . .
    [... C Code ...]

    🙄



  • Bashar schrieb:

    dot schrieb:

    janmerkschien schrieb:

    weiß jemand wieso das so ist ?

    Wil 9999.99 als double nicht exakt darstellbar ist.

    Aber ausreichend genug. Glaubst du ernsthaft, das double bei zulässigen 6 Stellen schon aufgibt? 9999.99 wird etwa als 9999.9899999999998 gespeichert.

    Offenbar ausreichend ungenau, dass es bei der Ausgabe auf 10000 gerundet wurde, obwohl die precision des stream auf einem Wert > 0 steht...



  • dot schrieb:

    Offenbar [speichert double die Zahl] ausreichend ungenau, dass es bei der Ausgabe auf 10000 gerundet wurde, obwohl die precision des stream auf einem Wert > 0 steht...

    Die Zahl 99999,99 wird bei ieee-754 64bit Kodierung mit dem Wert 99999,9900000000052... approximiert. Und wenn ich
    99999,9900000000052...
    auf höchstens 6 Stellen runde, komme ich auf
    100000
    Wenn ich die Zahl auf 7 bis 15 Stellen runde, komme ich genau auf
    99999,99



  • 314159265358979 schrieb:

    Schlechte Lösung. Nimm dafür die IOStream-Manipulatoren.

    👍

    cout << setprecision(2) << setw(12) << d2 << endl;
    

    Und jetzt bitte nicht gleich über endl herfallen!



  • Eben. Also ist der Grund für die "falsche" Ausgabe, dass die Zahl 9999.99000... als double nicht exakt darstellbar ist. Die Anzahl der "Kommastellen" die ein double packt, ist natürlich sehr viel größer als 2, das spielt aber im konkreten Fall keine Rolle. Mit 1024.25 gäbe es z.B. kein Problem. Nichts andres wollte ich mit meiner Antwort sagen. Der Grund, warum ich dann auf BCD verwiesen hab, war, dass ich davon ausging, dass der Threadersteller seine Zahlen dezimal exakt darstellen will...



  • dot schrieb:

    Also ist der Grund für die "falsche" Ausgabe, dass die Zahl 9999.99000... als double nicht exakt darstellbar ist. Die Anzahl der "Kommastellen" die ein double packt, ist natürlich sehr viel größer als 2, das spielt aber im konkreten Fall keine Rolle. Mit 1024.25 gäbe es z.B. kein Problem.

    Mit 9999.99 gibt es auch kein Problem, es gibt ein Problem mit 99999.99 (mein Fehler). Es gibt auch ein Problem mit 99999.75, welches zwar exakt darstellbar ist, aber als 99999.8 ausgegeben wird. Ob die Zahl exakt darstellbar ist oder nicht wirkt sich in der 15. Stelle oder so aus und ist bei der standardmäßigen Ausgabe von 7 Stellen schlicht irrelevant.



  • dot schrieb:

    Eben. Also ist der Grund für die "falsche" Ausgabe, dass die Zahl 9999.99000... als double nicht exakt darstellbar ist.

    Nein. Das ist falsch. Das ist nicht der Grund. Der Standard garantiert, dass double mindestens auf 10 Stellen genau ist. Das reicht für die Ausgabe von 99999.99 dicke aus. Man muss nur schlau genug sein, dem stream-Objekt auch mitzuteilen, dass es mehr als 6 Dezimalstellen anzeigen soll, da 99999.99 ja schon 7 Dezimalstellen hat.



  • Bashar schrieb:

    dot schrieb:

    Also ist der Grund für die "falsche" Ausgabe, dass die Zahl 9999.99000... als double nicht exakt darstellbar ist. Die Anzahl der "Kommastellen" die ein double packt, ist natürlich sehr viel größer als 2, das spielt aber im konkreten Fall keine Rolle. Mit 1024.25 gäbe es z.B. kein Problem.

    Mit 9999.99 gibt es auch kein Problem, es gibt ein Problem mit 99999.99 (mein Fehler). Es gibt auch ein Problem mit 99999.75, welches zwar exakt darstellbar ist, aber als 99999.8 ausgegeben wird. Ob die Zahl exakt darstellbar ist oder nicht wirkt sich in der 15. Stelle oder so aus und ist bei der standardmäßigen Ausgabe von 7 Stellen schlicht irrelevant.

    Stimmt, sry, Denkfehler meinerseits, hab mir doch irgendwie tatsächlich eingebildet, die Abweichungen könnten beim Runden nach vorn propagieren 🤡



  • Lassen wir doch einfach das Programm und den Prozessor mit der vom Datentyp double vorgegebenen Anzahl signifikanter Stellen Werte speichern und rechnen. Die gewünschte Ausgabe in eine Dezimalzahl erledigen fremde oder eigene Funktionen zuverlässig. 🤡

    Niemand (ausser das Eichamt) fragt an der Wursttheke, wie die Waage das gewünschte Gewicht von 200 g wiegt. Hauptsache die Anzeige ist hinreichend genau zuverlässig und wir bezahlen, was wir kriegen! Wer kommt auf die Idee, er hätte 0,00000999 Cent zuviel zu zahlen? 😕


  • Mod

    berniebutt schrieb:

    Wer kommt auf die Idee, er hätte 0,00000999 Cent zuviel zu zahlen? 😕

    Anwälte?



  • berniebutt schrieb:

    Lassen wir doch einfach das Programm und den Prozessor mit der vom Datentyp double vorgegebenen Anzahl signifikanter Stellen Werte speichern und rechnen. Die gewünschte Ausgabe in eine Dezimalzahl erledigen fremde oder eigene Funktionen zuverlässig. 🤡

    Ganz so einfach ist es leider nicht. Ein double speichert 53 binäre Stellen in der Mantisse, aber das bedeutet nicht, dass dein Ergebnis auch diese Genauigkeit hat. Multiplikation und Division sind da relativ harmlos, aber Addition und Subtraktion können leicht dazu führen, dass der Fehler sich weit nach oben verschiebt. Ich nenne da gern das Beispiel einer numerischen Ableitung per Differenzenquotient:

    double numeric_derivative(std::function<double(double)> const &func, double x, double epsilon) {
      return (func(x + epsilon) - func(x - epsilon)) / (2 * epsilon);
    }
    

    Diese kann man zum Beispiel für ein Newton-Verfahren auf hinreichend gutmütigen Funktionen benötigen. Es kann dabei leicht passieren, dass func(x + epsilon) und func(x - epsilon) sehr nahe beieinander liegen - in der Tat könnte man auf die Idee kommen, dass die Ergebnisse um so genauer sein müssten, je kleiner das Epsilon ist. Das Problem ist: beide Ergebnisse mögen auf 53 binäre Stellen genau sein, aber wenn beispielsweise die ersten 40 davon gleich sind, dann hat die Differenz nur noch eine effektive Mantisse von 13 binären Stellen (Abweichungen zu erwarten in der vierten dezimalen Nachkommastelle). Die Wahl des richtigen Epsilons ist da ein Balanceakt - mit größeren Epsilon werden kleinere Teile der Mantisse verloren, dafür ist aber die Näherung der Ableitung dann mathematisch ungenauer.

    Richtig lustig wird das natürlich, wenn man mal eine zweite Ableitung braucht.

    Es ist also nicht so, dass man den Prozessor und das Programm mit Fließkommazahlen einfach machen lassen kann, zumindest nicht unter allen Umständen. Es ist schon Fingerspitzengefühl gefragt, und mitunter ist es besser, in den sauren Performanceapfel zu beißen und auf eine MP-Bibliothek auszuweichen.

    berniebutt schrieb:

    Wer kommt auf die Idee, er hätte 0,00000999 Cent zuviel zu zahlen?

    Oh, nicht zu zahlen, aber damit gerechnet wird routinemäßig. Wenn man alle Geldbeträge auf Cent rundet, handelt man sich jede Menge unstetige Funktionen ein, wo man sie in den Modellen überhaupt nicht brauchen kann. Ich kann keinen Spread ausrechnen, wenn meine Kursfunktion nicht differenzierbar ist.



  • berniebutt schrieb:

    Wer kommt auf die Idee, er hätte 0,00000999 Cent zuviel zu zahlen? 😕

    Natürlich kommt es immer auf die Größenverhältnisse an. Wenn man ne Anwendung baut, bei der man bereits standardmäßig alles logarithmiert um irgendwie mit den zahlenbereichen hinzukommen, dann werden auf einmal wieder 15 Stellen nach dem Komma relevant.



  • otze schrieb:

    Natürlich kommt es immer auf die Größenverhältnisse an. Wenn man ne Anwendung baut, bei der man bereits standardmäßig alles logarithmiert um irgendwie mit den zahlenbereichen hinzukommen, dann werden auf einmal wieder 15 Stellen nach dem Komma relevant.

    Könnten wir so stehen lassen. Float-Zahlen kennen intern aber keine Nachkommastellen, nur Mantisse und Exponent meines Wissens auf der Basis 2. Deshalb spricht man dort besser von der Anzahl signifikanter Stellen (Vorkomma + Nachkomma). Alles weitere müssen Funktionen (standard oder eigene) machen, damit man es ordentlich lesen kann.

    Im übrigen sind viele Dinge, die gerechnet werden, ohnehin angenäherte Modelle einer komplexeren Wirklichkeit. Was das Modell an Genauigkeit nicht hergibt, können die letzten Nachkommastellen auch nicht zeigen. Kriegst du auch mit Logarithmen nicht hin!

    Das alles führt nun aber weit weg vom ursprünglichen Thema 'runden von double'.


Anmelden zum Antworten