Wie drucke ich mit cout einen doppelten Wert mit voller Genauigkeit?

Lesezeit: 10 Minuten

Wie drucke ich mit cout einen doppelten Wert mit voller
Jason Punyon

In meiner früheren Frage habe ich a gedruckt double verwenden cout das wurde abgerundet, als ich es nicht erwartet hatte. Wie kann ich machen cout drucke a double mit voller Präzision?

  • Leider sind die meisten der folgenden Antworten falsch. Ich empfehle stattdessen, sich stackoverflow.com/questions/19610161/… anzusehen.

    – vitaut

    17. Dezember 2020 um 19:23 Uhr

  • Beachten Sie, dass es nicht wirklich so etwas wie “volle” Genauigkeit gibt.

    – Muhende Ente

    19. Juli 2021 um 21:40 Uhr

  • @MooingDuck Wenn Sie das Double als Ganzzahl drucken, können Sie sicher sein, dass Sie alle Bits speichern … (cout << *reinterpret_cast<std::uint64_t *>(&my_double);) Dies ist nützlich, um Ihre Daten zu speichern und sie später Bit für Bit mit genau demselben Wert neu zu laden. Aber in den meisten Fällen ist das nicht das, was der Benutzer will.

    – Alexis Wilke

    16. Dezember 2021 um 18:32 Uhr

  • @AlexisWilke: std::hexfloat ist besser als Gießen, aber ja

    – Muhende Ente

    20. Dezember 2021 um 19:07 Uhr


  • @AlexisWilke Be sehr vorsichtig damit! Tippspiel ist leider in C++ schrecklich kaputt!

    – Niko O

    10. Februar um 13:06 Uhr

1647274209 18 Wie drucke ich mit cout einen doppelten Wert mit voller
Bill die Eidechse

Sie können die Genauigkeit direkt einstellen std::cout und benutze die std::fixed Formatbezeichner.

double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;

Du kannst #include <limits> um die maximale Präzision eines Floats oder Doubles zu erhalten.

#include <limits>

typedef std::numeric_limits< double > dbl;

double d = 3.14159265358979;
cout.precision(dbl::max_digits10);
cout << "Pi: " << d << endl;

  • Warum raten Sie ausdrücklich zur Verwendung fixed? Mit double h = 6.62606957e-34;, fixed gibt mir 0.000000000000000 und scientific Ausgänge 6.626069570000000e-34.

    – Arthur

    9. Januar 2012 um 17:58 Uhr

  • Die Genauigkeit muss 17 (oder std::numeric_limits::digits10 + 2) sein, da 2 zusätzliche Ziffern benötigt werden, wenn von der Dezimaldarstellung zurück in die binäre Darstellung konvertiert wird, um sicherzustellen, dass der Wert auf denselben ursprünglichen Wert gerundet wird. Hier ist ein Papier mit einigen Details: docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

    – Mike Fischer

    28. Oktober 2013 um 9:16 Uhr

  • Ist das wirklich die richtige Antwort? Wenn ich manuell eine hohe Zahl verwende, kann ich bis zu 51 Ziffern des ungefähren e ausdrucken, aber mit cout.precision(numeric_limits<double>::digits10 + 2); Ich bekomme nur 16….

    – Assimilator

    4. September 2014 um 22:07 Uhr

  • Für diejenigen, die suchen, wo in dem zitierten Artikel @MikeFisher 17 Ziffern erwähnt werden, steht es unter Theorem 15.

    – Emil Cormier

    11. Januar 2015 um 21:23 Uhr

  • @MikeFisher Du hast recht, C++11 führt ein max_digits10 dasselbe zu bezeichnen. Die Antwort wurde korrigiert, um dies widerzuspiegeln.

    – legends2k

    24. August 2015 um 7:47 Uhr

Wie drucke ich mit cout einen doppelten Wert mit voller
Paul Beckham

Verwenden std::setprecision:

#include <iomanip>
std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;

  • Gibt es eine Art MAX_PRECISION-Makro oder Aufzählung oder etwas, das ich an std::setPrecision übergeben kann?

    – Jason Punyon

    16. Februar 2009 um 18:23 Uhr

  • std::setprecision(15) für ein Double (ok oder 16), log_10(2**53) ~= 15.9

    – Benutzer7116

    16. Februar 2009 um 18:24 Uhr

  • std::setprecision(std::numeric_limits::digits10)

    – Eric Malenfant

    16. Februar 2009 um 18:42 Uhr

  • Sollte sein std::setprecision (17) für doppelt siehe Kommentare zur Antwort von @Bill The Lizard.

    – Alec Jacobson

    17. Dezember 2015 um 14:45 Uhr

  • damit std::setprecision funktioniert, sollte #include enthalten sein.

    – Benutzer2262504

    16. Juli 2016 um 8:34 Uhr

1647274210 972 Wie drucke ich mit cout einen doppelten Wert mit voller
Martin York

Hier ist, was ich verwenden würde:

std::cout << std::setprecision (std::numeric_limits<double>::digits10 + 1)
          << 3.14159265358979
          << std::endl;

Grundsätzlich hat das Limits-Paket Eigenschaften für alle eingebauten Typen.
Eines der Merkmale für Fließkommazahlen (Float/Double/Long Double) ist das Attribut digits10. Dies definiert die Genauigkeit (ich vergesse die genaue Terminologie) einer Gleitkommazahl in Basis 10.

Sehen: http://www.cplusplus.com/reference/std/limits/numeric_limits.html

Einzelheiten zu anderen Attributen.

  • Dieser Header wird zur Verwendung benötigt std::setprecision(): #include <iomanip>

    – Martin Berger

    19. August 2011 um 15:26 Uhr

  • es sollte sein std::numeric_limits<double> anstatt numberic_limits<double>

    – niklasfi

    15. April 2014 um 14:00 Uhr


  • Warum fügst du hinzu 1 zu std::numeric_limits<double>::digits10?

    – Alessandro Jacobson

    3. Oktober 2014 um 11:40 Uhr

  • @LokiAstari Sie können C + 11 verwenden max_digits10 stattdessen. Sieh dir das an.

    – legends2k

    25. August 2015 um 9:04 Uhr

  • @AlecJacobson Es sollte eher so sein max_digits10nicht irgendeine Willkür digits10+2. Ansonsten im Fall von float, long double, boost::multiprecision::float128 Dies wird fehlschlagen, da Sie dort benötigen würden +3 anstatt +2.

    – Ruslan

    27. Mai 2019 um 17:41 Uhr


1647274210 510 Wie drucke ich mit cout einen doppelten Wert mit voller
vitaut

In C++20 können Sie verwenden std::format um dies zu tun:

std::cout << std::format("{}", M_PI);

Ausgang (unter der Annahme von IEEE754 double):

3.141592653589793

Das Standard-Gleitkommaformat ist die kürzeste Dezimaldarstellung mit Roundtrip-Garantie. Der Vorteil dieser Methode gegenüber der setprecision E/A-Manipulator ist, dass er keine unnötigen Ziffern druckt.

In der Zwischenzeit können Sie verwenden die {fmt}-Bibliothek, std::format basiert auf. {fmt} bietet auch die print Funktion, die dies noch einfacher und effizienter macht (Gottriegel):

fmt::print("{}", M_PI);

Haftungsausschluss: Ich bin der Autor von {fmt} und C++20 std::format.

1647274211 369 Wie drucke ich mit cout einen doppelten Wert mit voller
Timotheus003

Der iostreams-Weg ist etwas klobig. Ich benutze lieber boost::lexical_cast weil es für mich die richtige Genauigkeit berechnet. Und Es ist schnellzu.

#include <string>
#include <boost/lexical_cast.hpp>

using boost::lexical_cast;
using std::string;

double d = 3.14159265358979;
cout << "Pi: " << lexical_cast<string>(d) << endl;

Ausgabe:

Pi: 3,14159265358979

  • In der Boost-Dokumentation heißt es: „Für Zahlen mit einer entsprechenden Spezialisierung von std::numeric_limits wählt die aktuelle Version jetzt eine entsprechende Genauigkeit“. Dies scheint der einfachste Weg zu sein, um die maximale Präzision zu erreichen. (boost.org/doc/libs/1_58_0/doc/html/boost_lexical_cast/…)

    – JDiMatteo

    15. Mai 2015 um 21:34 Uhr

  • Link mit boost::lexical_cast (boost.org/doc/libs/release/libs/conversion/lexical_cast.htm) ist tot.

    – chux – Wiedereinsetzung von Monica

    7. Oktober 2021 um 18:38 Uhr


  • Beachten Sie, dass das Drucken von a double mit nur 15 Ziffern wie bei “Pi: 3.14159265358979” wird möglicherweise nicht wieder in dasselbe umgewandelt double. Um das immer zu tun, braucht es mehr Likes max_digits10 wichtige Ziffer.

    – chux – Wiedereinsetzung von Monica

    7. Oktober 2021 um 18:41 Uhr

Wie drucke ich a double Wert mit voller Genauigkeit mit cout?

Verwenden hexfloat oder
verwenden scientific und stellen Sie die Genauigkeit ein

std::cout.precision(std::numeric_limits<double>::max_digits10 - 1);
std::cout << std::scientific <<  1.0/7.0 << '\n';

// C++11 Typical output
1.4285714285714285e-01

Zu viele Antworten sprechen nur eine von 1) Basis 2) festem/wissenschaftlichem Layout oder 3) Präzision an. Zu viele Antworten mit Präzision geben Sie nicht den richtigen Wert an, der benötigt wird. Daher diese Antwort auf eine alte Frage.

  1. Welche Basis?

EIN double ist sicherlich mit Basis 2 kodiert. Ein direkter Ansatz mit C++11 ist das Drucken mit std::hexfloat.
Wenn eine nicht dezimale Ausgabe akzeptabel ist, sind wir fertig.

std::cout << "hexfloat: " << std::hexfloat << exp (-100) << '\n';
std::cout << "hexfloat: " << std::hexfloat << exp (+100) << '\n';
// output
hexfloat: 0x1.a8c1f14e2af5dp-145
hexfloat: 0x1.3494a9b171bf5p+144

  1. Andernfalls: fixed oder scientific?

EIN double ist ein Fließkomma Typ, nicht Fixpunkt.

Machen nicht verwenden std::fixed da das nicht klein gedruckt werden kann double als alles andere als 0.000...000. Für groß doublees druckt vielleicht viele Ziffern Hunderte von fragwürdiger Aussagekraft.

std::cout << "std::fixed: " << std::fixed << exp (-100) << '\n';
std::cout << "std::fixed: " << std::fixed << exp (+100) << '\n';
// output
std::fixed: 0.000000
std::fixed: 26881171418161356094253400435962903554686976.000000 

Um mit voller Präzision zu drucken, verwenden Sie es zuerst std::scientific die “Gleitkommawerte in wissenschaftlicher Notation schreiben”. Beachten Sie den Standardwert von 6 Stellen nach dem Dezimalkomma, ein unzureichender Betrag wird im nächsten Punkt behandelt.

std::cout << "std::scientific: " << std::scientific << exp (-100) << '\n';  
std::cout << "std::scientific: " << std::scientific << exp (+100) << '\n';
// output
std::scientific: 3.720076e-44
std::scientific: 2.688117e+43

  1. Wie viel Genauigkeit (wie viele Stellen insgesamt)?

EIN double codiert mit der binären Basis 2 codiert die gleiche Genauigkeit zwischen verschiedenen Potenzen von 2. Dies sind häufig 53 Bit.

[1.0…2.0) there are 253 different double,
[2.0…4.0) there are 253 different double,
[4.0…8.0) there are 253 different double,
[8.0…10.0) there are 2/8 * 253 different double.

Yet if code prints in decimal with N significant digits, the number of combinations [1.0…10.0) is 9/10 * 10N.

Whatever N (precision) is chosen, there will not be a one-to-one mapping between double and decimal text. If a fixed N is chosen, sometimes it will be slightly more or less than truly needed for certain double values. We could error on too few (a) below) or too many (b) below).

3 candidate N:

a) Use an N so when converting from text-double-text we arrive at the same text for all double.

std::cout << dbl::digits10 << '\n';
// Typical output
15

b) Use an N so when converting from double-text-double we arrive at the same double for all double.

// C++11
std::cout << dbl::max_digits10 << '\n';
// Typical output
17

When max_digits10 is not available, note that due to base 2 and base 10 attributes, digits10 + 2 <= max_digits10 <= digits10 + 3, we can use digits10 + 3 to insure enough decimal digits are printed.

c) Use an N that varies with the value.

This can be useful when code wants to display minimal text (N == 1) or the exact value of a double (N == 1000-ish in the case of denorm_min). Yet since this is “work” and not likely OP’s goal, it will be set aside.


It is usually b) that is used to “print a double value with full precision”. Some applications may prefer a) to error on not providing too much information.

With .scientific, .precision() sets the number of digits to print after the decimal point, so 1 + .precision() digits are printed. Code needs max_digits10 total digits so .precision() is called with a max_digits10 - 1.

typedef std::numeric_limits< double > dbl;
std::cout.precision(dbl::max_digits10 - 1);
std::cout << std::scientific <<  exp (-100) << '\n';
std::cout << std::scientific <<  exp (+100) << '\n';
// Typical output
3.7200759760208361e-44
2.6881171418161356e+43
//2345678901234567  17 total digits

Similar C question

  • The boost documentation says “For numerics that have a corresponding specialization of std::numeric_limits, the current version now chooses a precision to match”. This seems like the easiest way to get the max precision. (boost.org/doc/libs/1_58_0/doc/html/boost_lexical_cast/…)

    – JDiMatteo

    May 15, 2015 at 21:34

  • Link with boost::lexical_cast (boost.org/doc/libs/release/libs/conversion/lexical_cast.htm) is dead.

    – chux – Reinstate Monica

    Oct 7, 2021 at 18:38


  • Note that printing a double with only 15 digits as with “Pi: 3.14159265358979” might not convert back to the same double. To always do that requires more like max_digits10 significant digits.

    – chux – Reinstate Monica

    Oct 7, 2021 at 18:41

Wie drucke ich mit cout einen doppelten Wert mit voller
Vikramaditya Kukreja

Here is how to display a double with full precision:

double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::setprecision(precision) << d << std::endl;

This displays:

100.0000000000005

max_digits10 is the number of digits that are necessary to uniquely represent all distinct double values. max_digits10 represents the number of digits before and after the decimal point.

Don’t use set_precision(max_digits10) with std::fixed.
On fixed notation, set_precision() sets the number of digits only after the decimal point. This is incorrect as max_digits10 represents the number of digits before and after the decimal point.

double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::fixed << std::setprecision(precision) << d << std::endl;

This displays incorrect result:

100.00000000000049738

Note: Header files required

#include <iomanip>
#include <limits>

  • This happens because 100.0000000000005 isn’t being represented exactly as a double. (It might seem like it should, but it doesn’t, because it gets normalised, i.e. its binary representation). To see this, try: 100.0000000000005 - 100. We get 4.973799150320701e-13.

    – Evgeni Sergeev

    Sep 8, 2017 at 12:12

1002290cookie-checkWie drucke ich mit cout einen doppelten Wert mit voller Genauigkeit?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy