C++-Gleitkommapräzision [duplicate]

Lesezeit: 1 Minute

C Gleitkommaprazision duplicate
Davinel

Mögliches Duplikat:

Beispiele für Fließkomma-Ungenauigkeiten

double a = 0.3;
std::cout.precision(20);
std::cout << a << std::endl;

Ergebnis: 0,2999999999999999889

double a, b;
a = 0.3;
b = 0;
for (char i = 1; i <= 50; i++) {
  b = b + a;
};
std::cout.precision(20);
std::cout << b << std::endl;

Ergebnis: 15.000000000000014211

Also .. ‘a’ ist kleiner als es sein sollte. Aber wenn wir ‘a’ 50 Mal nehmen, wird das Ergebnis größer sein, als es sein sollte.

Warum ist das? Und wie erhält man in diesem Fall das richtige Ergebnis?

  • Geh und lies darüber. Gleitkommaausgaben müssen sorgfältig studiert werden, damit Sie keine gefährlichen Fehler machen.

    – Artelios

    26. Mai 2010 um 0:26 Uhr

  • Um genaue Werte zu erhalten, verwenden Sie stattdessen Ganzzahlen (oder einige Bignum-Bibliotheken) const int acc=100; int tmp, a=30/acc, b=0; für (char i=1;i<=50;i++) b=b+a; std::cout << int(b/acc) << "."; tmp=b%acc; if (tmp<10) std::cout << "0"; std::cout << int (tmp); Um die Dinge zu beschleunigen, können Sie eine Potenz von 2 für acc verwenden, damit *,/,% in <<,>>,& umgewandelt wird.

    – Spektre

    20. August 2013 um 13:07 Uhr

1646316609 527 C Gleitkommaprazision duplicate
Kubbi

Um die richtigen Ergebnisse zu erhalten, stellen Sie die Genauigkeit nicht größer als für diesen numerischen Typ verfügbar ein:

#include <iostream>
#include <limits>
int main()
{
        double a = 0.3;
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << a << std::endl;
        double b = 0;
        for (char i = 1; i <= 50; i++) {
                  b = b + a;
        };
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << b << std::endl;
}

Wenn diese Schleife jedoch 5000 Iterationen statt 50 durchläuft, wird der akkumulierte Fehler auch bei diesem Ansatz angezeigt – so funktionieren Gleitkommazahlen.

  • +1 für numeric_limits sind definitiv nicht bekannt genug, wie sie sein sollten.

    – Kornel Kisielewicz

    26. Mai 2010 um 0:47 Uhr

C Gleitkommaprazision duplicate
dan04

Warum ist das?

Weil Gleitkommazahlen binär gespeichert werden, wobei 0,3 0,01001100110011001 ist … sich wiederholen, genau wie 1/3 0,333333 ist … sich dezimal wiederholen. Wenn du schreibst 0.3erhalten Sie tatsächlich 0,29999999999999988897769753748434595763683319091796875 (die unendliche binäre Darstellung, gerundet auf 53 signifikante Stellen).

Denken Sie daran, dass es für die Anwendungen, für die Gleitkommazahlen entwickelt wurden, kein Problem darstellt, dass Sie 0,3 nicht exakt darstellen können. Fließkomma wurde entwickelt, um verwendet zu werden mit:

  • Körperliche Messungen, die oft nur 4 sig Feigen und gemessen werden noch nie bis über 15.
  • Transzendente Funktionen wie Logarithmen und die trigonometrischen Funktionen, die sowieso nur angenähert werden.

Für die Binär-Dezimal-Umwandlungen im Vergleich zu anderen Fehlerquellen ziemlich irrelevant sind.

Nun, wenn Sie Finanzsoftware schreiben, was 0,30 $ bedeutet exakt 0,30 $, es ist anders. Für diese Situation gibt es dezimale Arithmetikklassen.

Und wie erhält man in diesem Fall das richtige Ergebnis?

Die Begrenzung der Genauigkeit auf 15 signifikante Stellen reicht normalerweise aus, um die “Rausch”-Ziffern zu verbergen. Es sei denn, Sie tatsächlich brauchen eine genaue Antwort, ist dies normalerweise der beste Ansatz.

  • Vielleicht könnten Sie am Ende Ihres ersten Absatzes ergänzen: “… weil die unendliche Reihe der binären Darstellung von 0,3 irgendwann abgeschnitten wird, weil unendliche Werte nicht auf einem Computer gespeichert werden können”.

    – josch

    18. August 2016 um 5:46 Uhr

Computer speichern Gleitkommazahlen binär, nicht dezimal.

Viele Zahlen, die dezimal normal aussehen, wie z. B. 0,3, haben keine exakte Darstellung der endlichen Länge im Binärformat.
Daher wählt der Compiler die nächste Zahl aus, die eine exakte binäre Darstellung hat, genau wie Sie schreiben 0.33333 zum 1⁄3.

Wenn Sie viele Fließkommazahlen addieren, summieren sich diese winzigen Unterschiede und Sie erhalten unerwartete Ergebnisse.

  • Ich denke, die Schlüsselantwort für das OP lautet: “Mit Gleitkommazahlen können Sie nicht das richtige Ergebnis erzielen.” 🙂

    – Dash-Tom-Bang

    26. Mai 2010 um 1:20 Uhr

  • Sie erhalten das richtige Ergebnis. Zugegeben, nicht das Ergebnis, das Sie erwartet haben.

    – MSalter

    26. Mai 2010 um 7:15 Uhr

Es ist nicht so, dass es größer oder kleiner ist, es ist nur physikalisch unmöglich, „0,3“ als exakten Wert in einer binären Gleitkommazahl zu speichern.

Der Weg zum “richtigen” Ergebnis besteht darin, keine 20 Dezimalstellen anzuzeigen.

Um das “richtige” Ergebnis zu erhalten, versuchen Sie es

Liste der arithmetischen Bibliotheken mit beliebiger Genauigkeit aus Wikipedia:
http://en.wikipedia.org/wiki/Arbitrary-precision

oder

http://speleotrove.com/decimal

  • Dezimal- und Arithmetik mit beliebiger Genauigkeit sind für die Zwecke des OP höchstwahrscheinlich nicht erforderlich.

    – dan04

    26. Mai 2010 um 5:09 Uhr

  • Dezimal- und Arithmetik mit beliebiger Genauigkeit sind für die Zwecke des OP höchstwahrscheinlich nicht erforderlich.

    – dan04

    26. Mai 2010 um 5:09 Uhr

924180cookie-checkC++-Gleitkommapräzision [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy