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?
Wie drucke ich mit cout einen doppelten Wert mit voller Genauigkeit?
Jason Punyon
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
? Mitdouble h = 6.62606957e-34;
,fixed
gibt mir0.000000000000000
undscientific
Ausgänge6.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
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
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>
anstattnumberic_limits<double>
– niklasfi
15. April 2014 um 14:00 Uhr
-
Warum fügst du hinzu
1
zustd::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_digits10
nicht irgendeine Willkürdigits10+2
. Ansonsten im Fall vonfloat
,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
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
.
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 umgewandeltdouble
. 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.
- 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
- Andernfalls:
fixed
oderscientific
?
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ß double
es 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
- 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/…)
– JDiMatteoMay 15, 2015 at 21:34
-
Link with boost::lexical_cast (boost.org/doc/libs/release/libs/conversion/lexical_cast.htm) is dead.
– chux – Reinstate MonicaOct 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 samedouble
. To always do that requires more like max_digits10 significant digits.– chux – Reinstate MonicaOct 7, 2021 at 18:41
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 adouble
. (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 get4.973799150320701e-13
.– Evgeni SergeevSep 8, 2017 at 12:12
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