Alle Nachkommastellen eines float/double ausgeben
-
Hi!
Ich möchte gerne alle Nachkommastellen eines float bzw. double ausgeben, aber irgendwie funkt das nicht so wirklich. Soweit ich weiß, kann man mit std :: fixed eine Festkommadarstellung auf der Konsole wählen und mit std :: cout.precision(x) die Anzahl der Nachkommastellen wählen.
Im Programm habe ich dann z.B. folgende Ausgabe://... double a; //... std :: cout.precision(100); std :: cout << "a = " << std :: fixed << a << std :: endl;
Nach IEEE-754 kann ein double 15-16 Nachkommastellen haben (siehe auch: http://de.wikipedia.org/wiki/Ieee754#Zahlenformate_und_andere_Festlegungen_des_IEEE-754-Standards), also würde ich jetzt erwarten, dass bei der Darstellung von a nach spätestens 16 Nachkommastellen nur noch 0en kommen. Leider bricht die Darstellung nicht einmal nach 100 Zeichen ab, sondenr enthält immernoch Ziffern != 0.
Ich hab das Ganze auf einer 64Bit Maschine kompiliert, jedoch gibt mir sizeof(double) auch 8 Byte an, also genausoviel wie ich auch für einen double erwarte. Irgendwie muss doch die Ausgabe dann falsch sein, weil mit 64 Bit ist es unmöglich 100 Nachkommastellen zu speichern
Wo liegt der Fehler in der Ausgabe?Gruß
Pille
-
Das liegt daran, dass die Daten im binären Format gespeichert werden. Bei der Umwandlung in das dezimale System können beliebig viele Stellen rauskommen.
Simples Beispiel: Wenn du ein Drittel im dreier-System schreibst, hat es genau eine Nachkommastelle: (0.1)3 Ausgegeben im Dezimalsystem steh da dann 0.33333333333333333333333333...
-
"fixed" ist 'ne blöde Idee.
Nein, die Ausgabe ist nicht falsch.
Richtig, mit 64 Bit kann man nicht 100 Dezimalstellen speichern.Stell Dir den Zahlenstrahl vor. Stell Dir darauf Kreuzchen vor, die Werte repräsentieren, die durch ein 64-bit-double darstellbar sind. Aufgrund der 64 Bit haben die Kreuzchen einen bestimmten Abstand zu einander; denn es gibt ja nur 2^64 verschiedene 64bit-Kombinationen und man kann den Zahlenstrahl nicht "feiner" auflösen, weil man dann mehr als 2^64 Kreuzchen bräuchte. Das heißt aber nicht, dass ein Kreuzchen zwischen 1.0 und 2.0 für einen Wert stehen muss, der nach 16 dezimalen Nachkommastellen nur noch Nullen hat. Die Abstände der Kreuzchen ensprechen dem, was man mit ca 16 Dezimalstellen auflösen kann, aber die genaue Position der Kreuzchen liegt ggf woanders. Und das kommt daher, dass typischerweise eine binäre Darstellung (also mit Einsen und Nullen) statt einer Dezimaldarstellung für die Kodierung verwendet wird.
Für einen verlustfreien Roundtrip von double -> string -> double
benötigst du nur 17 Dezimalstellen (insgesamt, also die vor UND nach dem Komma)Für einen verlustfreien Roundtrip von string -> double -> string
musst du die Zahl der Dezimalstellen im Eingangsstring auf höchstens 15 begrenzen, damit das klappt.(unter der Annahme der IEEE 754 64-Bit Float Kodierung)
Auch erwähnenswert: Verwechsle Stellen nicht mit Nachkommastellen.
-
pumuckl schrieb:
Das liegt daran, dass die Daten im binären Format gespeichert werden. Bei der Umwandlung in das dezimale System können beliebig viele Stellen rauskommen.
Das ist so nicht ganz korrekt, weil 2 ein Teiler von 10 ist; wenn eine Zahl im Binärsystem endlich viele Nachkommastellen hat, hat sie es auch im Dezimalsystem. Wenn ich mich grad nicht verrechne, lässt sich jeder ieee754-double mit höchstens 565 dezimalen Nachkommastellen genau darstellen (so viele hat 2-(512+53)).
Die Unterschiede in der Darstellung dürften im Zweifel von Rundungsfehlern bei der Umrechnung vom Binär- ins Dezimalsystem herrühren.