Die Multiplikation von zwei floats nicht geben genaue Ergebnis
Ich versuche multiplizieren von zwei float
s wie folgt:
float number1 = 321.12;
float number2 = 345.34;
float rexsult = number1 * number2;
Den Ergebnissen, die ich sehen wollen, ist 110895.582, aber wenn ich den code ausführen, es macht mir einfach 110896. Die meiste Zeit bin ich mit diesem Problem. Jeder Rechner gibt mir das genaue Ergebnis mit allen Nachkommastellen. Wie kann ich erreichen, dass Ergebnis?
edit : Es ist C code. Ich bin mit XCode iOS simulator.
- Ist das C, oder Java? Es kann entweder aus dem, was Sie gezeigt haben.
- Und sollten Sie
double
stattfloat
. - Sind Sie sicher, dass Sie nicht einfach abschneiden, wenn Sie es drucken? Wie hast du den Wert, den Sie bekommen?
- Ich benutzte double zu, Gleiches Ergebnis.
- Sie einfach nur gedruckt das Ergebnis auf 6 stellen. das ist default in C++, aber das können Sie ändern. In C++, zum Beispiel, mit
std::cout<<std::setprecision(16)<<x;
- Ich sah das Ergebnis in der Variablen Bereich der XCode IDE. Wenn ich es drucken mit "%f", es zeigt alle Dezimalstellen. Aber
std::ostringstream stringStream;
stringStream << rexsult;
char * utf8Bytes = strdup(stringStream.str().c_str());
hier utf8Bytes abgerundet ist, auch.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es gibt eine Menge der Rundung geht.
Bekomme ich 110895.578125000000000 nach den drei separaten Rundungen.
Wenn Ihr mehr als 6 Dezimalstellen im Wert von Präzision, Sie wird haben Verwendung
double
und nichtfloat
. (Beachten Sie, dass ich sagte: "dezimal-Ziffern "Wert", weil Sie nicht bekommen, Dezimalstellen, erhalten Sie binäre.) So wie es da steht, 1/2 ULP-Fehler (worst-case-Schranke für eine perfekt gerundetes Ergebnis) ist etwa 0.004.Wenn Sie möchten, genau gerundeten Dezimalzahlen, müssen Sie eine spezielle dezimal-Bibliothek für solch eine Aufgabe. Ein
double
hat mehr als genug Präzision für Wissenschaftler, aber wenn Sie arbeiten mit Geld, das alles hat zu 100% genau. Keine floating-point-zahlen für Geld.Im Gegensatz zu Ganzzahlen, Gleitkomma-zahlen nehmen einige echte Arbeit, bevor Sie sich daran gewöhnen können, Ihre Tücken. Siehe "Was Jeder Computer Scientist Should Know About Floating-Point Arithmetic", das ist die klassische Einführung in das Thema.
Edit: Eigentlich, ich bin mir nicht sicher, dass der code Runden drei mal. Es könnten Runde fünf Zeiten, da die Konstanten für
a
undb
vielleicht zuerst gerundet mit doppelter Genauigkeit und dann zu single-precision, wenn Sie gelagert werden. Aber ich weiß nicht, die Regeln dieses Teil C sehr gut.double
und dann zufloat
ist identisch mit Rundung auffloat
direkt. Wenn ich war auf der Suche nach einem unschuldig aussehenden Dezimalzahl zwischen 1 und 2 mit doppelter Rundung Probleme für den Zweck der blog.frama-c.com/index.php?post/2011/11/08/Floating-point-quiz , ich musste 14 stellen nach dem Punkt. Ich konnte nicht finden, dass jeder mit nur 13 Ziffern.Werden Sie nie das genaue Ergebnis, dass Art und Weise.
Zunächst Zahl1 ≠ 321.12, weil dieser Wert nicht exakt dargestellt werden, die in Basis-2-system. Sie müssen eine unendliche Anzahl von bits für es.
Dasselbe gilt auch für die Zahl2 ≠ 345.34.
So, Sie beginnen mit ungenauen Werten beginnen mit.
Dann wird das Produkt abgerundete da die Multiplikation gibt verdoppeln Sie die Anzahl der signifikanten stellen, aber das Produkt gelagert werden muss, in
float
wieder, wenn Sie multiplizieren schwimmt.Werden Sie wahrscheinlich wollen, um mit einem 10-basierten system für Ihre zahlen. Oder, im Falle, das Ihre zahlen nur 2 Ziffern der Nachkommastellen, die Sie verwenden können, ganze zahlen (32 bit Ganzzahlen sind in diesem Fall ausreichend, aber Sie können am Ende brauchen 64-bit):
32112 * 34534 = 1108955808.
Darstellt 321.12 * 345.34 = 110895.5808.
Da man sich mit C konnte man leicht die Präzision durch die Verwendung von "%.xf" wobei x für die gewünschte Präzision.
Beispiel:
Ausgabe:
Beachten Sie jedoch, dass
float
gibt nur sechs Ziffern der Präzision. Für bessere Präzision verwendendouble
.Printf tut auch etwas Verrunden. Betrachten http://codepad.org/LLweoeHp:
Gut, es sieht gut aus. Warum? Weil printf standardmäßig auf einige präzise und abgerundet, die Ausgabe. Lassen Sie sich auf dem Zifferblatt in 50 stellen nach Dezimalpunkt: http://codepad.org/frUPOvcI
Ist das anders, nicht wahr? Nach 625 der Schwimmer lief die Kapazität für die Speicherung von mehr Daten, das ist der Grund, warum wir Nullen.
Ein double halten können mehr zahlen, aber von 0,1 in Binär ist nicht endlich. Doppel aufgeben, schließlich: http://codepad.org/RAd7Yu2r
In deinem Beispiel 321.12 allein ist genug, um Probleme verursachen: http://codepad.org/cgw3vUKn
Dies ist der Grund, warum man in der Runde Fließkomma-Werte, bevor Sie auf den Menschen.
Taschenrechner-Programme nicht verwenden, floats oder doubles überhaupt. Sie implementieren Dezimalzahl format. eg:
Ofc erfordert neu erfinden, alle Operationen: Hinzufügung, Abzug, Vermehrung und Abteilung. Oder einfach nur nach einem dezimal-Bibliothek.