Nutzen von Fließkommazahlen



  • Schön dass sich alle bei den einfachsten grundlegenden Datentypen so einig sind wie sie funktionieren 😃 Ich würde mal sagen zurück zum Start beim Programmieren lernen 😃 😃 😃



  • ???????? schrieb:

    Schön dass sich alle bei den einfachsten grundlegenden Datentypen so einig sind wie sie funktionieren.

    Die meisten Informatiker setzen sich mit Gleitkommaarithmetik nun einmal nicht wirklich auseinander. Es hat seien Gründe warum man Gleitkommaarithemtik mit Binär- und Dezimalformat, Intervalarithmetik auf Basis von Binärgleitkommaarithemtik, Libraries/Framworks für Gleitkomma mit beliebiger Genauigkeit, Festkommarithmetik und Integerarithmetik verwendet.


  • Administrator

    ~john schrieb:

    Das ist schlichtweg falsch! Dezimalgleitkommazahlen unterliegen bis auf eine Ausnahme exakt den gleichen Problemen wie die Binärgleitkommazahlen. Einzig das Problem der Nichtabbildbarkeit einiger Dezimalbrüche auf Binärbrüche und umgekehrt wird mit Dezimalgleitkommazahlen vermieden. Trotzdem muß man bei Verwendung der Dezimalgleitkommaarithmetik genauso aufpassen wie mit der Binärgleitkommarithmetik. Hinzu kommt, daß man durch die Dezimalkodierung noch etwas an Genauigkeit verliert. Daher empfiehlt sich das Dezimalformat nicht für technischwissenschaftliche Rechnungen.

    Schön wie du Sachen aus dem Kontext reisst und dann auch noch Dinge fett machst, sieht wirklich nett aus. Ich habe dies nicht für technischwissenschaftliche Rechnungen vorgeschlagen, sondern für Währungsrechnungen, also für die Verwendung in der Finanzwirtschaft und genau dafür wurden diese zusätzlichen Gleitkommazahlen geschaffen.
    Für technische Rechnungen, welche wirklich genau sein müssen, würde ich auch nicht Gleitkommazahlen heranziehen.

    hibbes schrieb:

    Ok, der Fehler war mehr als blöd. Warum gibt cout keine Gleitkommazahlen direkt aus?

    Wie ~john gesagt hat, wird gerundet. Gibt aber die Möglichkeit mehr Kontrolle darüber zu haben:
    http://www.cplusplus.com/reference/iostream/ios_base/precision/

    Hättest du in einem von mir präsentierten Code in diesem Thread bereits schon gesehen. Zusätzlich seien noch erwähnt:
    http://www.cplusplus.com/reference/iostream/manipulators/fixed/
    http://www.cplusplus.com/reference/iostream/manipulators/scientific/

    Grüssli


  • Mod

    Dravere schrieb:

    Für technische Rechnungen, welche wirklich genau sein müssen, würde ich auch nicht Gleitkommazahlen heranziehen.

    Ich bin allgemein etwas verwirrt über die Ansichten hier im Thread und über diese Aussage ganz besonders. Kannst du mir mal ein Beispiel nennen für welche technische Anwendung double nicht ausreichend sein soll? Für float kann ich noch ein paar Gegenbeispiele konstruieren, aber auch dies sind schon seltene Ausnahmefälle.

    Zum Thread: Wie ich im ersten Beitrag schon sagte: Niemand verwendet Fließkommazahlen nicht wegen mangelnder Genauigkeit. Man verwendet Fließkommazahlen nur dann nicht, wenn das Problem inhärent nach einem diskreten Zahlenmodell verlangt (z.B. Geld). Ich denke das Problem ist eher, dass viele Leute nicht wissen, wie man Sachen richtig modelliert. Sie sehen eine Zahl mit einem Komma drin und denken nur "Oh, da muss ich Fließkommazahlen nehmen", obwohl dies eigentlich gar nicht angemessen wäre. Fließkommazahlen sind die Digitalcomputerannäherung für das Kontinuum (mit ein paar Fallstricken auf die man aufpassen muss). Das Komma ist nicht das entscheidende Feature!

    Viele der Probleme die hier aufgezählt werden erinnern mich daran, wie wenn Anfänger Kontonummern, Postleitzahlen oder Telefonnummern als Ganzzahlen speichern und dann in Schwierigkeiten kommen. Der Fehler liegt in der falschen Modellierung (eine Ziffernfolge ist keine Zahl!), nicht im Datentyp.



  • ~john schrieb:

    Finanzmathematische Rechnungen werden dagegen nicht mit Gleitkommaarithmetik gerechnet.

    Das ist so nicht ganz korrekt. Gleitkommazahlen sind eine schlechte Idee, wenn es um Geldbeträge geht und Haargenauigkeit verlangt wird - wenn auf einer Rechnung nicht genau der vereinbarte Preis steht, ist das ziemlich peinlich - aber in der Finanzmathematik, wie sie beispielsweise im Wertpapierhandel betrieben wird, sind die meisten relevanten Größen betragsneutral. Wenn ein Händler Wertpapiere vergleichen muss, ist deren Volumen nur am Rande interessant; die Frage ist üblicherweise der Form "wie viel kriege ich im Verhältnis zu dem raus, was ich reinstecke?", weswegen nahezu alles in Prozent ausgewiesen wird.

    Und da sind 15 Stellen Genauigkeit mehr als ausreichend, zumal vieles eh Ansichts- oder Konventionssache ist. In der Praxis kuckt eh selten einer hinter die vierte Nachkommastelle, wenn es nicht um gesetzlich/vertraglich festgelegte Dinge wie etwa Stückzinsen geht, und auch da ist es so, dass ein Rundungsfehler bei 15 Stellen Genauigkeit sich auch bei Milliardenbeträgen höchstens auf einen Cent beläuft.

    Das deckt sich auch mit dem, was SeppJ schreibt und dem ich nur von Herzen zustimmen kann.



  • Man kann Haare spalten. Dann werden aus einem Haar zwei oder mehr. Die Diskussion hier ist so ähnlich und trifft nicht die Fragestellung.

    Fliesskommazahlen sind sehr genau, genauer als alles andere. Nur nicht in der allerletzten Stelle hinter dem Komma. Das was hier als Festkommazahlen offeriert wird sind entweder gerundete Fliesskommazahlen oder simple Ganzzahlen mit Multiplikation. Ganzzahlen haben viel früher eine Grenze der Genauigkeit.



  • seldon schrieb:

    und auch da ist es so, dass ein Rundungsfehler bei 15 Stellen Genauigkeit sich auch bei Milliardenbeträgen höchstens auf einen Cent beläuft.

    Das Problem ist eher die Fehlerfortpflanzung, wodurch die deutlich größere Fehler bekommen kannst.


  • Administrator

    SeppJ schrieb:

    Dravere schrieb:

    Für technische Rechnungen, welche wirklich genau sein müssen, würde ich auch nicht Gleitkommazahlen heranziehen.

    Ich bin allgemein etwas verwirrt über die Ansichten hier im Thread und über diese Aussage ganz besonders. Kannst du mir mal ein Beispiel nennen für welche technische Anwendung double nicht ausreichend sein soll? Für float kann ich noch ein paar Gegenbeispiele konstruieren, aber auch dies sind schon seltene Ausnahmefälle.

    Es geht um die Art, wie mit Gleitkommazahlen gerechnet wird. Es entstehen die ganze Zeit leichte Ungenauigkeiten, welche sich über die Zeit aufsummieren. Ich hatte erst letzten wieder ein Problem mit double . Es ging darum eine Simulation zu schreiben, wobei double verwendet wurde für die Positionsangaben (war nicht meine Entscheidung!). Dabei sind bereits auf Distanzen von 3-5 Metern Abweichungen von 1-5 Grad aufgetreten. Wenn man dies auf dein Beispiel mit der Rakete hochrechnet, dann würdest du wohl Gefahr laufen, bei der Landung neben der Erde durchzufliegen 😉

    Man muss nie vergessen, dass Gleitkommazahlen nur eine Approximation des gewollten Wertes darstellen und immer einen gewissen Fehlerwert mitführen. In grossen Rechnungen, welche dann womöglich auch noch oft gemacht werden, werden diese Fehler immer wieder mitgeführt und fangen an sich zu summieren. Es geht also nicht um die Darstellung einer einzelnen Zahl!

    SeppJ schrieb:

    Viele der Probleme die hier aufgezählt werden erinnern mich daran, wie wenn Anfänger Kontonummern, Postleitzahlen oder Telefonnummern als Ganzzahlen speichern und dann in Schwierigkeiten kommen. Der Fehler liegt in der falschen Modellierung (eine Ziffernfolge ist keine Zahl!), nicht im Datentyp.

    Daran erinnert mich der Thread irgendwie überhaupt nicht. Das ist doch ein ganz anderes Problem. Wie gesagt, es geht nicht um die Darstellung einer Zahl, sondern um das Rechnen mit dieser Zahl. Ich glaube eher, dass genau dies das Problem von einigen hier ist. 15-16 Stellen Genauigkeit bei der Darstellung, heisst nicht, dass auch das Ergebnis einer Rechnung eine Genauigkeit von 15-16 Stellen hat.

    Grüssli



  • Also nachdem ich das bei Wikipedia gelesen habe, bleibe ich dabei Gleitkomma nur einzusetzen wenn das Ergebnis nicht genau sein muss.

    Gab es nicht auch schon Probleme wenn man mit 0.1 oder so rechnen muss? Das kannst du dann 10 mal addieren und kommst aber nie auf 1. Das konnte ich zwar bei mit nicht feststellen, ist aber wohl in Excel mit VBA so. Also diese Zahlen sind wohl wirklich mit größter Vorsicht zu geniessn.


  • Mod

    hibbes schrieb:

    Also nachdem ich das bei Wikipedia gelesen habe, bleibe ich dabei Gleitkomma nur einzusetzen wenn das Ergebnis nicht genau sein muss.

    Gab es nicht auch schon Probleme wenn man mit 0.1 oder so rechnen muss? Das kannst du dann 10 mal addieren und kommst aber nie auf 1. Das konnte ich zwar bei mit nicht feststellen, ist aber wohl in Excel mit VBA so. Also diese Zahlen sind wohl wirklich mit größter Vorsicht zu geniessn.

    Nein, sind sie nicht. Wenn dein Zahlenraum nur aus Zehntelwerten besteht, dann hast du den falschen Datentyp gewählt. Wenn du hingegen mit reellen Zahlen recchnen willst, dann ist die Abweichung egal. Wen interessiert, dass 10 Holzstücke a 0.1m hintereinandergelegt in Fließkommaarithmetik 0.9999999999999999999 m sind und nicht 1m? Niemand wird jemals solch präzise Werkstücke oder Maßstäbe fertigen um den Unterschied zu messen.
    (Ok, derzeit stoßen wir in diese Dimensionen vor. Die am genauesten bekannten physikalischen Größen knabbern derzeit an der 15-Stellen-Grenze. Will man theoretische Rechnungen mit diesen Größen machen (welche keine ungenaueren Größen enthalten), dann muss man einen noch genaueren Datentyp wählen. Das ändert aber nichts daran, dass Fließkommazahlen dennoch die richtige Wahl sind, denn niemanden stört es, dass das long-double Ergebnis hinterher in der 30. nachkommastelle Fehler hat.)

    @Dravere: Das ist interessant. Ich mache ja selber auch physikalische Simulationen und hatte nie solche Probleme. War vielleicht der Algorithmus ungeeignet? Oder war eine unglaublich große Zahl von Rechenschritten (mehr als 10^10) nötig? Dennoch ist die Lösung für solche Probleme nur eine höhere Fließkommapräzision. Die ach so exakten Ganzzahlen würden alles nur schlimmer machen, denn Positionsangaben sind nun einmal kontinuierlich und daher FLießkommazahlen das geeignete Computermodell (Wenn ihr keine Gittertheorie macht. Dann wäre das falsch.).



  • SeppJ schrieb:

    Das ändert aber nichts daran, dass Fließkommazahlen dennoch die richtige Wahl sind, denn niemanden stört es, dass das long-double Ergebnis hinterher in der 30. nachkommastelle Fehler hat.

    Ist es nicht so, dass bei long double nur der Exponent größer wird, die Mantisse aber immer noch 4 Byte lang ist?



  • Hmm, scheint ja dann doch zu funktionieren wenn man rundet. Aber wie sieht es bei Gleichungen aus wenn ich eine 1.0 mit der 0.999999999999 vergleiche? Muss man da nicht extremst aufpassen?



  • hibbes schrieb:

    Hmm, scheint ja dann doch zu funktionieren wenn man rundet. Aber wie sieht es bei Gleichungen aus wenn ich eine 1.0 mit der 0.999999999999 vergleiche? Muss man da nicht extremst aufpassen?

    Musst du, deswegen wird empfohlen, mit einem gewissen Abweichungswert zu vergleichen:

    bool equal(double a, double b)
    {
        return fabs(a-b) <= std::numeric_limits<double>::epsilon;
    }
    


  • Super danke, das kannte ich auch noch nicht. Kommt gleich in die Notizen 👍



  • wxSkip schrieb:

    Musst du, deswegen wird empfohlen, mit einem gewissen Abweichungswert zu vergleichen:

    bool equal(double a, double b)
    {
        return fabs(a-b) <= std::numeric_limits<double>::epsilon;
    }
    

    Ja, aber nicht mit epsilon , sondern einer dem konkreten Problem angepassten Toleranz. epsilon bezeichnet nur die Differenz zwischen 1 und dem nächstgrösseren darstellbaren Wert.



  • Nexus schrieb:

    wxSkip schrieb:

    Musst du, deswegen wird empfohlen, mit einem gewissen Abweichungswert zu vergleichen:

    bool equal(double a, double b)
    {
        return fabs(a-b) <= std::numeric_limits<double>::epsilon;
    }
    

    Ja, aber nicht mit epsilon , sondern einer dem konkreten Problem angepassten Toleranz. epsilon bezeichnet nur die Differenz zwischen 1 und dem nächstgrösseren darstellbaren Wert.

    OK, aber im Fall von 0.999999999999999 passt das schon 🙂



  • Dravere schrieb:

    Ich habe dies nicht für technischwissenschaftliche Rechnungen vorgeschlagen, sondern für Währungsrechnungen, also für die Verwendung in der Finanzwirtschaft und genau dafür wurden diese zusätzlichen Gleitkommazahlen geschaffen.

    Wie schön, daß Du nicht einmal merkst, daß exakt in dem von Dir geschlagenem Anwendungsfeld es trotzdem die schon erwähnten Probleme gibt!



  • seldon schrieb:

    Und da sind 15 Stellen Genauigkeit mehr als ausreichend, zumal vieles eh Ansichts- oder Konventionssache ist.

    Fehlerfortpflanzung ist wohl für viele ein Fremdwort. 15 Stellen Genauigkeit wären wundervoll, wenn ein jedes Ergebnis damit ausgegeben würde. Allerdings ist die effektive Genauigkeit bei einer Berechnung oftmals sehr viel geringer, und der Rest der Stellen im Grunde nur Rauschen des Algorithmus. Das wird leider viel zu oft vergessen.



  • Kann man denn nicht irgendwie festmachen für was man Gleitkommazahlen ohne Einschränkung und besonderer Behandlung nutzen kann und wo man sehr genau aufpassen sollte?


  • Administrator

    ~john schrieb:

    Dravere schrieb:

    Ich habe dies nicht für technischwissenschaftliche Rechnungen vorgeschlagen, sondern für Währungsrechnungen, also für die Verwendung in der Finanzwirtschaft und genau dafür wurden diese zusätzlichen Gleitkommazahlen geschaffen.

    Wie schön, daß Du nicht einmal merkst, daß exakt in dem von Dir geschlagenem Anwendungsfeld es trotzdem die schon erwähnten Probleme gibt!

    😕
    Willst du eigentlich alles bewusst falsch verstehen? Lies bitte nochmals, was ich wie geschrieben habe.
    Neue Gleitkommazahlen des neuen Standards mit höherer Genauigkeit und neuer Rechnungskonvention für die Finanzwirtschaft. So schwer zu verstehen? Ich sage nicht, dass dadurch alle Probleme eliminiert werden! Aber sie werden deutlich reduziert und reichen meistens für die Finanzen.

    @SeppJ,
    Ich kann deine Fragen schlecht beantworten. Das einzige, was ich dazu sagen kann, ist, dass Motoren simuliert wurden. In kleinen Intervallen (ca. 1 - 2 Millisekunden) wurde die Position der Motoren aktualisiert und danach über Odometrie die aktuelle Position des Vehikels berechnet. Die Motoren hatten eine sehr geringe Geschwindigkeit (0,1 - 0,4 m/s). Auch ging es grundsätzlich immer um den Nullpunkt im 2D Raum, wodurch nie wirklich grosse Zahlen entstanden. Auch der Winkel wurde immer wieder nach einer 360° Umdrehung zurückgesetzt.

    Wir haben dann zum Teil mitgerechnet und festgestellt, dass nach jeder Rechnung ein kleiner Fehler entstand. Dieser Fehler wurde abgespeichert als Position und mit dieser Position dann die nächste berechnet, Odometrie eben 🙂
    Dadurch hat sich dieser Fehler immer fortgepflanzt und es kam zu der erwähnten Abweichung. Wir konnten den Fehler auf nichts anderes zurückführen.

    Am Projekt hat es nicht wirklich geschadet, da in der Realität die Motoren sowieso nicht durch einen einzigen Befehl gleichzeitig die Geschwindigkeit ändern konnten, sondern nur sequentiell von einer höheren Abstraktionsebene aus. Zudem liefen sie nicht genau gleich schnell. Daher haben wir in der Simulation gleich noch den Positionskorrektur-Code dazugeschaltet, welche wir aber eigentlich bei der Simulation nicht dabei haben wollten. Das war aber nur ein kleines Projekt, vielleicht haben wir wirklich was falsch gemacht.

    Aber wie ich weiter vorne gesagt habe, hatte ich mal double für Währungen eingesetzt. Ist allerdings schon länger her. Da gab es bereits bei Beträgen von mehreren Hunderttausend Abweichungen von 2 - 3 Cent. Spielte dort zwar keine Rolle, da der Betrag am Ende sowieso abgerundet wurde, da man keine xxxx.99 Rechnungen haben wollte. Die Kunden wurden somit nie irgendwie betrogen, die Firma hat aber über das Jahr ein paar Euro verloren 😉
    Wenn man die Beträge aber wirklich genau hätte haben wollen, so wäre double definitiv der falsche Typ gewesen, weil er einfach zu ungenau ist.

    Mir ist es ehrlich gesagt ein Rätsel, wie du bisher noch nie Probleme mit double haben konntest.

    Grüssli


Anmelden zum Antworten