¿Cómo imprimo un valor doble con total precisión usando cout?

10 minutos de lectura

¿Como imprimo un valor doble con total precision usando cout
Jason Punyon

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?

  • 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

1647628747 526 ¿Como imprimo un valor doble con total precision usando cout
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? Con double h = 6.62606957e-34;, fixed me da 0.000000000000000 y scientific salidas 6.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

¿Como imprimo un valor doble con total precision usando cout
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

1647628748 455 ¿Como imprimo un valor doble con total precision usando cout
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 de numberic_limits<double>

    – niklasfi

    15/04/2014 a las 14:00


  • porque agregas 1 para std::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_digits10no algo arbitrario digits10+2. De lo contrario, en el caso de float, 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


1647628749 56 ¿Como imprimo un valor doble con total precision usando cout
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.

1647628749 403 ¿Como imprimo un valor doble con total precision usando cout
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 mismo double. 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.

  1. ¿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

  1. De lo contrario: fixed o scientific?

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 doubleimprime 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

  1. ¿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/…)

    – 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

¿Como imprimo un valor doble con total precision usando cout
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

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad