modf liefert falsche Werte
-
Hallo,
ich habe ein Problem mit modf(). Wenn ich mir z.B die Zahl 8811,0635 in Ganzahl- und Dezimalteil zerlegen lasse, kommt für den Dezimalteil sowas wie 0.063500000000203727 dabei heraus. Deswegen erhalte ich in meinen Programm falsche Werte.Hier der Beispiel-Quellcode:
double IntegerPart; double DecimalPart = std::modf(8811.0635);DecimalPart hat dann den Wert 0.063500000000203727.
Wodran liegt es, dass modf solche Werte liefert?Ich hoffe ihr könnt mir helfen.
-
Weil immer 8811.06350000000020372681319713592529296875 drin war. Viele Dezimalzahlen passen in einen double nämlich nicht ganz genau rein. Deswegen mußt der Compiler die nächstliegende reinstopfen, die eben um 0.00000000000020372681319713592529296875 größer war.
-
Das liegt daran, dass endlich lange Dezimalzahlen im Binärsystem (das dein Computer benutzt) teilweise unendlich lang sein können. So wie das Ergebnis von 1/3 im Dezimalsystem 0,333... ist, in einem System zur Basis 3 ist es aber exakt 0,1. Die Zahl 0,0635 zählt anscheinend zu diesen Zahlen (ich hab's jetzt nicht nachgerechnet). Da der Computer aber nur eine endliche Zahl von Stellen speichern kann, muss er die Zahl irgendwo runden. Und wenn man dann wieder zurückrechnet, bekommt man im Dezimalsystem einen geringfügig anderen Wert als vorher.
Wenn ich andererseits nachfragen darf: Was hast du denn für ein Problem, bei dem eine Zahl auf mehr als 12 Nachkommastellen genau sein muss?
-
SeppJ schrieb:
Das liegt daran, dass endlich lange Dezimalzahlen im Binärsystem (das dein Computer benutzt) teilweise unendlich lang sein können. So wie das Ergebnis von 1/3 im Dezimalsystem 0,333... ist, in einem System zur Basis 3 ist es aber exakt 0,1. Die Zahl 0,0635 zählt anscheinend zu diesen Zahlen (ich hab's jetzt nicht nachgerechnet). Da der Computer aber nur eine endliche Zahl von Stellen speichern kann, muss er die Zahl irgendwo runden. Und wenn man dann wieder zurückrechnet, bekommt man im Dezimalsystem einen geringfügig anderen Wert als vorher.
Wenn ich andererseits nachfragen darf: Was hast du denn für ein Problem, bei dem eine Zahl auf mehr als 12 Nachkommastellen genau sein muss?
Ich muss wissen wie viele Stellen eine Zahl insgesamt hat. Dazu habe ich folgenden Code:
template<class T> unsigned int getNumberOfDigits(T number) { T IntegerPart; T DecimalPart = std::modf(number, &IntegerPart); unsigned int NumberOfDigits = 1; //Die Zahlen sollten normalerweise größer oder gleich 1 sein if(IntegerPart == 0) { //Bei Zahlen kleiner als 1 soll die 0 vor dem Komma nicht mit gezählt werden NumberOfDigits = 0; } for(; (IntegerPart / 10) >= 1; NumberOfDigits++) { IntegerPart /= 10; } for(; std::modf(DecimalPart, &IntegerPart) != 0; NumberOfDigits++) { DecimalPart *= 10; } return NumberOfDigits; }
-
Henry Rust schrieb:
Ich muss wissen wie viele Stellen eine Zahl insgesamt hat.
Das geht nicht. Bereits 0.1 ist nicht genau als double darstellbar.
Du könntest allenfalls die Zahl mit << zum Beispiel in einen stringstream ausgeben und die ausgegebenen Ziffern zählen. Das wäre zwar nicht genauer, aber gleichwillkürlich wie die gewohnte Ausgabe auf cout.
-
Ok, dann kann ich mein gesamtes Programm neu schreiben.
Trotzdem danke!
-
Du solltest vielleicht ein exaktes und dynamisches Format verwenden. Es gibt sicher vorgefertigte Libraries dafür, aber zur Not würde es auch ein Container mit Ziffern tun.
-
Oder Bruchzahlen.
-
Gute Idee. Für Brüche gäbs mit Boost.Rational sogar was in Boost.
-
Das lernt man bereits in der Schule oder in der Mathevorlesung: in jedem Zahlensystem (hier dezimal = 10) gibt es zwischen zwei darstellbaren Zahlen unendlich viele weitere. Wo ist das Problem? Eine tatsächlich genaue Anzahl Nachkommastellen gibt es nicht.