filestream float aus datei und die genauigkeit
-
Hi ich hab hier ein kleines Problem mit meinem Program.
Ich öffne einen filestream und versuche eine Zahl einzulesen.
Es ist eine einfache Tabelle und ich brauche sie unbedingt für die weitere Verarbeitung als double. Die zahl ist im jedem Editor /more/less/cat sagt das selbe einfach
2452585.44260
Versuche ich diese jetzt mit
inputFile>>f_time;
einzulesen. Un gebe ich sie dannach wieder aus. Fix point so erhalte ich
cout<<f_time;
2452585.4426000002.
Diese kleine 2 am Ende macht mir im Laufe des Programs Probleme. Weshalb ist die zahlk nicht glatt? Weshalb dieser Rundungsfehler.
Hoffe jemand kann mir helfen.THANX Lex
Alexander Gahr
-
Hallo Lex,
Eine Zahl in der für uns vertrauten Dezimaldarstellung wird in Deinem PC binär - d.h. als eine Folge von Nullen und Einsen - abgelegt. Nun ist nicht jede - scheinbar einfache - Dezimalzahl glatt in eine Binärzahl umzurechnen. Zum Beispiel ist 1,2 dezimal in binär %1,00110011001100110011 ... usw. bis in alle Ewigkeit. Der Computer muss 1,2 also binär runden, um sie z.B. in eine Variable abzuspeichern. Bei der Darstellung in Dezimalform - das passiert bei 'cout << variable' - kann sich nun dieser Rundungsfehler bemerkbar machen. Bei Ausgabe mit voller Genauigkeit erhält man u.U. 1,199999999999 oder 1,2000000000001.
Und das ist auch der Trick. Beschränke die Genauigkeit Deiner Ausgabe. Wenn f_time ein double von der Größe 8 Byte ist, so ist sowieso bei ca. 14 Dezimalstellen Schluß. Wenn Du schreibst
#include <iostream> #include <iomanip> ... double v = 2452585.4426; std::cout << std::setprecision(12) << v << std::endl;.. sollte die Ausgabe wieder der Dezimaldarstellung entsprechen. Du erhälst die Anzahl der möglichen Dezimalstellen die Dein Typ darstellen kann mit
#include <limits> ... std::cout << "max. Anzahl Dezimalstellen: " << std::numeric_limits< f_time >::digits10 << std::endl;Gruß
Werner
-
Danke für deine Hilfe das mit dem runden war mir schon klar.
Hab nur irgendwie gedacht bei double wäre die precision 16 wegen 32 bit Maschine.sizeof(double)=8
bei der Maschine.
Hm auf meiner 32 Bit Maschine sagt der nur 15 da geht bestimmt eins fürs Vorzeichen weg oder ist das ganze wegen dieser Rundung? Komischerweise habe ich das Problem bei FORTRAN90 DOUBLE PRECISION nicht. Denn kann ich mit 16 Stellen ausgeben.
Super dieses Befehl mit Limit zu kennen, hoffe nur das der SunWorkshop Compiler das auch kennt.
Überigens du meintest bestimmt
std::cout << "max. Anzahl Dezimalstellen: " << std::numeric_limits<double>::digits10 << std::endl;
oder?
Danke aber vielmals.
-
AlexKid schrieb:
Hab nur irgendwie gedacht bei double wäre die precision 16 wegen 32 bit Maschine.
sizeof(double)=8
bei der Maschine.
Hallo Alex,
In einem double (oder float) wird eine Fließkomma-Zahl in Form einer Mantisse und eines Exponenten abgespeichert. Also dezimal z.B.:
-345,78 = -3,45678 * 10^2
0,00123 = 1,23 * 10^-3
hier in meinem Beispiel liegt die Mantisse immer im halboffenen Intervall [1, 10). Und für die Genauigkeit ist nur die Anzahl der Stellen der Mantisse ausschlaggebend. Neben der Mantisse muss der Rechner noch das Vorzeichen, den Exponenten und das Vorzeichen des Exponenten in den z.B.8 Bytes unterbringen.AlexKid schrieb:
Hm auf meiner 32 Bit Maschine sagt der nur 15 da geht bestimmt eins fürs Vorzeichen weg oder ist das ganze wegen dieser Rundung? Komischerweise habe ich das Problem bei FORTRAN90 DOUBLE PRECISION nicht. Denn kann ich mit 16 Stellen ausgeben.
Ich glaube nicht, dass es da anders ist, da das verwendete Format mehr von der CPU als von der Programmiersprache abhängt. Du kannst auch in C++ mit beliebig vielen Stellen ausgeben; aber es wird deshalb nicht genauer (siehe Dein Posting oben).
AlexKid schrieb:
Überigens du meintest bestimmt
std::cout << "max. Anzahl Dezimalstellen: " << std::numeric_limits<double>::digits10 << std::endl;
oder?
Eigentlich meinte ich std::numeric_limits< Typ-von-f_time >::digits10; Du hast uns den Typ von f_time ja noch nicht verraten

Gruß
Werner