Nutzen von Fließkommazahlen



  • theliquidwave schrieb:

    Welche Alternativen gibt es in C++ denn? Implementierungen oder wie? Die müssen doch letztlich auch mit dem selben Brot backen, oder nicht?!

    Kommt eben immer auf das Einsatzgebiet an.
    Nein - fließkommazahlen sind ja deshalb so toll, weil alle operationen in der hardware(fpu) ausgeführt werden.
    man hat ja noch die möglichkeit, sich etwas eigenes zu bauen.
    für geld-beträge bietet sich z.bsp. einfach nur eine ganz einfache lösung an:

    struct money_t
    {
    public:
      explicit money_t(int euro = 0, int cent = 0)
      : cent(euro*100+cent)
      {}
    
      int get_euro() const
      {
        return cent/100;
      }
      unsigned char get_cent() const
      {
        return unsigned char(cent%100);
      }
    private:
      int cent;
    };
    

    für unendlich genaue zahlen gibt es ja z.bsp. brüche (zumindest für die rationalen).
    für die irrationalen gibt es so und so keine genaue lösung...

    bb



  • In Cent rechnen ist eine gute Idee, aber man muss mit der Breite ein bisschen aufpassen - bei der Staatsverschuldung sind wir in Deutschland beispielsweise schon über einer Billion Euro, und 100 Billionen Cent kriegt man in einen 32-bit-Integer nicht mehr rein. Wie lange ein 64-bit-Integer reicht, bleibt abzuwarten. 😞


  • Administrator

    theliquidwave schrieb:

    Welche Alternativen gibt es in C++ denn? Implementierungen oder wie? Die müssen doch letztlich auch mit dem selben Brot backen, oder nicht?!

    Es gibt aber verschiedene Möglichkeiten, wie man backen kann 😉
    Unskilled und der Threadersteller haben bereits zwei Methoden genannt: Festkommazahl und Bruchdarstellung. Zudem gibt es noch die BCD Möglichkeit (Binary Coded Decimal). BCD erlaubt es grundsätzlich nur, beliebig grosse Zahlen darzustellen und mit ihnen zu rechnen. Dank der Methode der Festkommazahl kann man dann aber beliebig genaue und grosse Dezimalzahlen darstellen. Die einzige Grenze stellt dann die Performance und RAM-Speichergrösse dar. Wobei man natürlich auch auf die Festplatte ausweichen könnte, aber die Performance wäre dann noch schlimmer, als sie bereits durch BCD Zahlen ist. Es gibt zum Teil BCD Chips, aber ich glaube, dass die in einer Standard-CPU wohl kaum vorhanden sind.

    Grüssli



  • seldon schrieb:

    In Cent rechnen ist eine gute Idee, aber man muss mit der Breite ein bisschen aufpassen - bei der Staatsverschuldung sind wir in Deutschland beispielsweise schon über einer Billion Euro, und 100 Billionen Cent kriegt man in einen 32-bit-Integer nicht mehr rein. Wie lange ein 64-bit-Integer reicht, bleibt abzuwarten. 😞

    Bleibt abzuwarten? Nun, lange genug gewartet 😉 . Bei einem 64-Bit signed Integer (und den brauchst du für das Staatsguthaben 😃 ) ist der Maximalwert 2^63-1 und der Minimalwert -2^63. Also kann der Staat noch ca. 9223372035154775807 Euro Schulden machen. 😮



  • Hi,

    hier mal ein Beispiel wie ungenau ein float sein kann.

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        float a = 1.23456789f,
              b = 1.23f,
              c = 0.0f;
    
        c = a - b;
        cout << "a - b = " << c << endl;
    }
    

    Als Ergebnis sollte 0.00456789 rauskommen. Das Programm erzeugt bei mir stattdessen diese Ausgabe hier:

    a - b = 0.0045678[b]6[/b]
    

    Also Fließkommazahlen nur einsetzen wenn das Ergebnis auch mal leicht abweichen darf, ansonsten Festkomma etc. verwenden.

    G hibbes



  • _malsogefragt schrieb:

    Ja davon habe ich auch schon gehört, ich meine das man Fließkommazahlen nicht mal für Buchhaltungsgeschichten einsetzen kann. Tja, wozu sind sie denn dann bloss zu gebrauchen bzw für was setzt ihr sie mit ruhigem Gewissen ein?

    Bei allen naturwissenschaftlichen und ingenieurwissenschaftlichen Aufgaben! :p
    Hier sind float und double oft nahezu unverzichtbar. Habt ihr in der Schule auch nur mit ganzen Zahlen gerechnet? Zwischen je zwei ganzen Zahlen gibt es unendlich viele nichtganze Zahlen. Diese stellt man gewöhnlich als Fliesskommazahlen dar.

    Zwei sehr einfache Beispiele:
    1. die Berechnung des Schnittpunktes zweier Geraden.
    2. die Fläche innerhalb eines Polygons (Linienzug), z.B. zur Bestimmung einer Grundstücksgrösse im m².



  • Ich glaube der Threadersteller wollte wissen warum man Fließkommazahlen anstelle von Festkommazahlen verwendet. Beide können ja mit reellen Zahlen rechnen, nur sind die Fließkommazahlen dabei ungenau aber schnell, und die Festkommazahlen genau aber langsamer.

    Ich glaube gelesen zu haben das z.B. Taschenrechner nur mit Festkommazahlen arbeiten.

    G hibbes


  • Administrator

    @hibbes,
    Bisschen billig das Beispiel nicht? Da float nur auf maximal 7 Stellen genau sein kann, scheitert dein Beispiel bereits bei der Initialisierung von a . Statt die Rechnung durchzuführen und noch zwei weitere Variablen reinzunehmen, könntest du auch gleich a ausgeben.
    Wenn du dein Programm allerdings auf double umstellen würdest, wäre alles korrekt, da double auf maximal 16 Stellen genau ist.

    Hier vielleicht mal zwei sinnvolle Beispiele:

    int main()
    { 
      double a = 0.333;
      std::cout.precision(20);
    
      std::cout << (a * 3.0) << std::endl;
      // 0.33300000000000002 * 3.0 = 0.99900000000000011
    
      a = 1.0 / 3.0;
      std::cout << a << " * 3.0 = " << (a * 3.0) << std::endl;
      // 0.33333333333333331 * 3.0 = 1
    
      std::cin.get();
      return 0;
    }
    

    Beim ersten Beispiel sieht man gut, dass auch wenn man Zahlen nimmt, welche dargestellt werden können, es hinter den genauen Stellen Artefakte gibt.

    Das zweite Beispiel sieht zwar korrekt aus, ist aber zum Beispiel gerade bei Finanzen unerwünscht. Es gibt keine Möglichkeit eine Periode zu speichern. Somit sollte es hier nur ein 0.9999999999999999 ausgeben. In den Finanzen will man diese Rundung auf 1 selber durchführen und dies vor allem erst ganz am Schluss. Sonst wird die ganze Zeit in den Rechnungen bereits gerundet, was am Ende zu einem Rundungsfehler führt.
    Meine bisherigen Erfahrungen haben gezeigt, dass dieser Rundungsfehler schnell mal 2-3 Cent ausmachen kann, bei noch relativ kleinen Beträgen (< 1 Mio).

    Grüssli



  • hibbes schrieb:

    und die Festkommazahlen genau aber langsamer.

    Je nach dem, was man macht. Hat man es viel mit Addition und Subtraktion zu tun, sind Festkommazahlen so schnell wie int.

    Ich glaube gelesen zu haben das z.B. Taschenrechner nur mit Festkommazahlen arbeiten.

    Ich weiß nicht. Mir sehen die http://www.oldcalculatormuseum.com/ nach Fließkommazahlen aus.



  • @Dravere: ja hast recht, mein Beispiel war Mist :p

    @Volkard: das sind ja mal ein paar Rechenmaschinen, wo kommen da die Clowns raus? 😃



  • wxSkip schrieb:

    seldon schrieb:

    In Cent rechnen ist eine gute Idee, aber man muss mit der Breite ein bisschen aufpassen - bei der Staatsverschuldung sind wir in Deutschland beispielsweise schon über einer Billion Euro, und 100 Billionen Cent kriegt man in einen 32-bit-Integer nicht mehr rein. Wie lange ein 64-bit-Integer reicht, bleibt abzuwarten. 😞

    Bleibt abzuwarten? Nun, lange genug gewartet 😉 . Bei einem 64-Bit signed Integer (und den brauchst du für das Staatsguthaben 😃 ) ist der Maximalwert 2^63-1 und der Minimalwert -2^63. Also kann der Staat noch ca. 9223372035154775807 Euro Schulden machen. 😮

    Och, das kriegt der im nächsten Jahrhundert noch hin. Wir befinden uns bei Verzinsung ja im Bereich von Exponentialfunktionen.

    Wie dem auch sei, Fließkommazahlen können ganz andere Bereiche abdecken als Festkommazahlen gleicher Größe, und es gibt viele Anwendungen, in denen es auf ein paar Millionen nicht ankommt, wenn man gerade mit Trilliarden in der Gegend rumjongliert. Gleichzeitig werden Fließkommazahlen bei sehr kleinen Beträgen überaus genau - man mag zwar selten mit Mikrocent rechnen müssen, aber Nanometer können durchaus mal vorkommen.



  • wxSkip schrieb:

    seldon schrieb:

    In Cent rechnen ist eine gute Idee, aber man muss mit der Breite ein bisschen aufpassen - bei der Staatsverschuldung sind wir in Deutschland beispielsweise schon über einer Billion Euro, und 100 Billionen Cent kriegt man in einen 32-bit-Integer nicht mehr rein. Wie lange ein 64-bit-Integer reicht, bleibt abzuwarten. 😞

    Bleibt abzuwarten? Nun, lange genug gewartet 😉 . Bei einem 64-Bit signed Integer (und den brauchst du für das Staatsguthaben 😃 ) ist der Maximalwert 2^63-1 und der Minimalwert -2^63. Also kann der Staat noch ca. 9223372035154775807 Euro Schulden machen. 😮

    Sollte man sich dann nicht mal überlegen, ob man die Gleitkomma-Arithmetik anpaßt,
    so dass Deutschland :schland: nach einem Überlauf wieder schuldenfrei ist? 🤡



  • Also wenn ich mir so den Wikipediaartikel durchlese muss man gar nicht in einen Mikrocentbreich gehen um mit Fließkommazahlen böse Überraschungen zu erleben. In dem Artikel sind Punkte aufgeführt wie:

    - Auslöschung
    - Zahlen verschiedener Größenordnungen
    - Unterlauf
    - Ungültigkeit des Assoziativgesetzes
    - Ungültigkeit des Distributivgesetzes

    http://de.wikipedia.org/wiki/Gleitkommazahl

    Ich habe mal das mit den verschiedenen Größenordnungen getestet und wenn ich nix falsch gemacht habe würde ich nie und nimmer die Fließkommazahlen für kaufmännische Rechnungen einsetzten wollen. Für Gleichungen scheinen sie auch nicht so geeignet zu sein wie im Artikel steht.

    #include <iostream>
    
    int main()
    {
        double a = 1000,
               b = 0.001,
               c = 0.0;
    
        c = a + b;
        std::cout << "a + b = " << c << std::endl;
    }
    

    Ausgabe ist hier 1000 und nicht 1000.001 und das bei double 😮 . Ich muss da mal wieder einen Fehler gemacht haben, oder?

    G hibbes



  • hibbes schrieb:

    #include <iostream>
    
    int main()
    {
        double a = 1000,
               b = 0.001,
               c = 0.0;
    
        c = a + b;
        std::cout << "a + b = " << c << std::endl;
    }
    

    Ausgabe ist hier 1000 und nicht 1000.001 und das bei double 😮 . Ich muss da mal wieder einen Fehler gemacht haben, oder?

    Ja, std::cout verwendet.

    int main()
    {
        double a = 1000,
               b = 0.001,
               c = 0.0;
    
        c = a + b;
        printf("%f", c);
    }
    


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



  • _malsogefragt schrieb:

    Für was werden denn Fließkommazahlen eingesetzt wenn sie so ungenau sind?

    Gleitkommarithemtik wird immer dann verwendet, wenn man für technischwissenschaftliche Rechnungen eine Approximation von reellen oder komplexen Zahlen benötigt. Natürlich treten dabei Probleme auf, aber es gehört nun einmal zu den Aufgaben eines Naturwissenschaftlers oder Ingenieurs zu wissen, wann dies der Fall ist.

    Festkommazahlen sind keine Alternative für SciTech Rechnungen, da sie viel zu langsam sind. Finanzmathematische Rechnungen werden dagegen nicht mit Gleitkommaarithmetik gerechnet.



  • hibbes schrieb:

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

    Doch, das ist der Fall. Nur wird bei der Ausgabe gerundet.



  • Dravere schrieb:

    Es gibt inzwischen bessere Fliesskommazahlen, welche sehr viel genauer sind und auch keine ungewollten Rundungen beinhalten. In C# gibt es zum Beispiel dazu System.Decimal . IEEE Standards wären hier 854-1987 und 754-2008 zu nennen.

    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 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.


Anmelden zum Antworten