4 Stimmen

Wie kann man verhindern, dass ostringstream (o.ä.) die wissenschaftliche Notation OHNE Präzisionseinstellung ausgibt?

Ich kann nicht glauben, dass ich nicht weiß, wie ich das machen soll, aber was soll ich sagen, ich weiß es nicht. Ich versuche nur, die Zahlen in Standard Format (im Gegensatz zur wissenschaftlichen Notation).

Ich habe zahllose Beispiele gelesen, wie man dies mit "setprecision(...)" und "fixed" und so weiter erreichen kann, aber das Problem ist, dass die Genauigkeit der Zahlen zur Kompilierzeit nicht bekannt ist und die Eingabe einer konservativen Schätzung mit "setprecision(...)" haufenweise überflüssige Nullen an der Stelle hinterlässt.

Hier ist ein Beispiel für das, was ich suche:

let: tau = 6.2831

tau * 0.000001 -> 0.0000062831
tau * 0.001    -> 0.0062831
tau            -> 6.2831
tau * 1000     -> 6283.1
tau * 1000000  -> 6283100

Im Moment bekomme ich:

tau * 0.000001 -> 6.2831e-006
tau * 0.001    -> 0.0062831
tau            -> 6.2831
tau * 1000     -> 6283.1
tau * 1000000  -> 6.2831e+006

Das einzige, was ich tun kann, ist, irgendwie extrahieren Sie den Exponenten der doppelten dann, wenn der Exponent positiv ist "fix" die Präzision auf Null, andernfalls setzen Sie die Präzision auf "-1 * exp"; aber dies scheint wie eine extrem verworrene Weise zu "ausschalten" wissenschaftliche Notation. Kennt jemand einen besseren Weg?

1 Stimmen

Sie bekämen offensichtlich Probleme mit z.B. tau * 1e-80 Das ist wahrscheinlich der Grund, warum es keine einfache Lösung gibt. - Übrigens, was hat es mit tau * 1000000 -> 6.2831e-006 ?

1 Stimmen

Das Problem ist, dass die meisten Dezimalbrüche nicht genau durch eine binäre Fließkommazahl dargestellt werden können (die so gut wie jede C++-Implementierung für ihre eingebauten Fließkommatypen verwendet). Wenn ich zum Beispiel auf meinem Computer definiere float tau = 6.2831 dann ist der tatsächliche Wert 6.283100128173828125 . Der Formatierer kann nicht wissen, dass die letzten 14 Ziffern auf einen Rundungsfehler zurückzuführen sind.

0 Stimmen

Tatsächlich ist es sogar so, dass es könnte vertreten 6.2831 genau, dann wäre es immer noch gleich 6.28310 . Es gibt keine "überflüssigen Nullen" in einer Darstellung mit fester Größe. Wenn Sie unterscheiden wollen zwischen 6.2831 y 6.28310 müssen Sie Folgendes verwenden std::string .

1voto

AProgrammer Punkte 49452

Während die meisten Dezimalbrüche nicht exakt durch eine binäre FP-Zahl dargestellt werden können und die exakte Darstellung einer binären FP-Zahl zu vielen Ziffern führen kann, gibt es Algorithmen zur Formatierung einer binären FP-Zahl als einfachste Dezimalzahl, die als ursprüngliche FP-Zahl zurückgelesen wird, wenn ein bestimmter Umrechnungsmodus bei der Eingabe angenommen wird (d. h. 6,283100128173828125 wird als 6,2831 formatiert, aber die nächste darstellbare FP-Zahl wird mit 6 oder 7 Ziffern formatiert).

Leider gibt es bei formatierten IO in C++ (und in C) keine Möglichkeit, die Anwendung dieser Algorithmen anzufordern. %g von printf und die Standardeinstellung von IOStream ist die nächstgelegene, aber sie sind mit einer automatischen Wahl zwischen fester und wissenschaftlicher Notation gekoppelt, sie benötigen eine maximale Genauigkeit und die Begrenzung der Endung 0 ist nicht wirklich dasselbe (sie gehen von der exakten Dezimaldarstellung aus, sie versuchen nicht, die einfachste zu finden).

Beachten Sie, dass diese Algorithmen nicht wirklich einfach sind, da sie Mehrpräzisionsarithmetik erfordern.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X