En mi pregunta anterior estaba imprimiendo un double
utilizando cout
que se redondeó cuando no lo esperaba. como puedo hacer cout
imprimir un double
usando precisión completa?
¿Cómo imprimo un valor doble con total precisión usando cout?
Jason Punyon
Bill el lagarto
Puede establecer la precisión directamente en std::cout
y usa el std::fixed
especificador de formato.
double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;
Puede #include <limits>
para obtener la máxima precisión de un flotador o doble.
#include <limits>
typedef std::numeric_limits< double > dbl;
double d = 3.14159265358979;
cout.precision(dbl::max_digits10);
cout << "Pi: " << d << endl;
-
¿Por qué recomienda explícitamente usar
fixed
? Condouble h = 6.62606957e-34;
,fixed
me da0.000000000000000
yscientific
salidas6.626069570000000e-34
.– Arturo
9 de enero de 2012 a las 17:58
-
La precisión debe ser 17 (o std::numeric_limits
::digits10 + 2) porque se necesitan 2 dígitos adicionales al convertir de decimal a representación binaria para garantizar que el valor se redondee al mismo valor original. Aquí hay un documento con algunos detalles: docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html –Mike Fisher
28 de octubre de 2013 a las 9:16
-
¿Es realmente la respuesta correcta? Cuando uso manualmente un número alto, puedo imprimir hasta 51 dígitos de e aproximado, pero con
cout.precision(numeric_limits<double>::digits10 + 2);
solo tengo 16….– Asimilador
04/09/2014 a las 22:07
-
Para aquellos que buscan donde menciona 17 dígitos en el artículo citado por @MikeFisher, está bajo el Teorema 15.
– Émile Cormier
11 de enero de 2015 a las 21:23
-
@MikeFisher Tienes razón, C++11 presenta
max_digits10
para denotar lo mismo. Se corrigió la respuesta para reflejar esto.– leyendas2k
24 de agosto de 2015 a las 7:47
pablo beckingham
Utilizar std::setprecision
:
#include <iomanip>
std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;
-
¿Hay algún tipo de macro o enumeración MAX_PRECISION o algo que pueda pasar a std::setPrecision?
– Jason Punyon
16 de febrero de 2009 a las 18:23
-
std::setprecision(15) para un doble (ok o 16), log_10(2**53) ~= 15.9
– usuario7116
16 de febrero de 2009 a las 18:24
-
std::setprecision(std::numeric_limits
::digits10) –Éric Malenfant
16 de febrero de 2009 a las 18:42
-
Debiera ser
std::setprecision (17)
para el doble, vea los comentarios sobre la respuesta de @Bill The Lizard.–Alec Jacobson
17 dic 2015 a las 14:45
-
para que std::setprecision funcione, se debe incluir #include
. – usuario2262504
16 de julio de 2016 a las 8:34
martín york
Esto es lo que yo usaría:
std::cout << std::setprecision (std::numeric_limits<double>::digits10 + 1)
<< 3.14159265358979
<< std::endl;
Básicamente, el paquete de límites tiene características para todos los tipos integrados.
Una de las características de los números de coma flotante (flotante/doble/doble largo) es el atributo digits10. Esto define la precisión (olvidé la terminología exacta) de un número de punto flotante en base 10.
Ver: http://www.cplusplus.com/reference/std/limits/numeric_limits.html
Para obtener detalles sobre otros atributos.
-
Este encabezado es necesario para usar
std::setprecision()
:#include <iomanip>
– Martín Berger
19 de agosto de 2011 a las 15:26
-
debería ser
std::numeric_limits<double>
en lugar denumberic_limits<double>
– niklasfi
15/04/2014 a las 14:00
-
porque agregas
1
parastd::numeric_limits<double>::digits10
?– Alessandro Jacopson
3 oct 2014 a las 11:40
-
@LokiAstari Puedes usar C+11
max_digits10
en lugar de. Mira esto.– leyendas2k
25 de agosto de 2015 a las 9:04
-
@AlecJacobson Debería ser más bien
max_digits10
no algo arbitrariodigits10+2
. De lo contrario, en el caso defloat
,long double
,boost::multiprecision::float128
esto fallará, ya que allí necesitarías+3
en lugar de+2
.– Ruslán
27 mayo 2019 a las 17:41
vitalidad
En C++20 podrás usar std::format
para hacer esto:
std::cout << std::format("{}", M_PI);
Salida (asumiendo IEEE754 double
):
3.141592653589793
El formato de punto flotante predeterminado es la representación decimal más corta con una garantía de ida y vuelta. La ventaja de este método en comparación con el setprecision
El manipulador de E/S es que no imprime dígitos innecesarios.
Mientras tanto puedes usar la biblioteca {fmt}, std::format
está basado en. {fmt} también proporciona la print
función que lo hace aún más fácil y más eficiente (perno de dios):
fmt::print("{}", M_PI);
Descargo de responsabilidad: Soy el autor de {fmt} y C++20 std::format
.
timoteo003
El camino de iostreams es un poco torpe. prefiero usar boost::lexical_cast
porque calcula la precisión correcta para mí. Y es rápidotambién.
#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;
Producción:
Pi: 3.14159265358979
-
La documentación de boost dice “Para valores numéricos que tienen una especialización correspondiente de std::numeric_limits, la versión actual ahora elige una precisión para que coincida”. Esta parece ser la forma más fácil de obtener la máxima precisión. (boost.org/doc/libs/1_58_0/doc/html/boost_lexical_cast/…)
– JDiMatteo
15 mayo 2015 a las 21:34
-
Enlace con boost::lexical_cast (boost.org/doc/libs/release/libs/conversion/lexical_cast.htm) está muerto.
– chux – Reincorporar a Monica
7 oct 2021 a las 18:38
-
Tenga en cuenta que imprimir un
double
con solo 15 dígitos como con “Pi: 3.14159265358979” podría no volver a convertirse al mismodouble
. Para hacer eso siempre se requiere más like max_digits10 dígitos significantes.– chux – Reincorporar a Monica
7 oct 2021 a las 18:41
¿Cómo imprimo un
double
valor con total precisión usando cout?
Utilizar hexfloat
o
utilizar scientific
y establecer la precisión
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
Demasiadas respuestas abordan solo una de 1) base 2) diseño fijo/científico o 3) precisión. demasiadas respuestas con precisión no proporciona el valor adecuado necesario. De ahí esta respuesta a una vieja pregunta.
- ¿Qué base?
A double
ciertamente está codificado usando base 2. Un enfoque directo con C++ 11 es imprimir usando std::hexfloat
.
Si una salida no decimal es aceptable, hemos terminado.
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
- De lo contrario:
fixed
oscientific
?
A double
es un punto flotante tipo, no punto fijo.
Hacer no utilizar std::fixed
como eso no se imprime pequeño double
como cualquier cosa menos 0.000...000
. Para grande double
imprime muchos dígitos, tal vez cientos de dudosa informatividad.
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
Para imprimir con total precisión, primer uso std::scientific
que “escribirá valores de punto flotante en notación científica”. Fíjese que el valor predeterminado de 6 dígitos después del punto decimal, una cantidad insuficiente, se maneja en el siguiente punto.
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
- ¿Cuánta precisión (cuántos dígitos en total)?
A double
codificado usando la base binaria 2 codifica la misma precisión entre varias potencias de 2. Esto suele ser de 53 bits.
[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
Lamentablemente, la mayoría de las respuestas a continuación son incorrectas. Recomiendo consultar stackoverflow.com/questions/19610161/… en su lugar.
– vitalidad
17 de diciembre de 2020 a las 19:23
Tenga en cuenta que en realidad no existe tal cosa como una precisión “total”.
– Pato mugido
19/07/2021 a las 21:40
@MooingDuck En realidad, si imprime el doble como un número entero, entonces puede estar seguro de guardar todos los bits… (
cout << *reinterpret_cast<std::uint64_t *>(&my_double);
) Esto es útil para guardar sus datos y volver a cargarlos más tarde con exactamente el mismo valor, bit a bit. Pero en la mayoría de los casos eso no es lo que quiere el usuario.– Alexis Wilke
16 dic 2021 a las 18:32
@AlexisWilke:
std::hexfloat
es mejor que casting, pero si– Pato mugido
20 dic 2021 a las 19:07
@AlexisWilke Ser muy cuidado con eso! ¡Desafortunadamente, el juego de palabras está horriblemente roto en C ++!
– Niko O.
10 de febrero a las 13:06