c++ - poner - ¿Cómo imprimo un valor doble con total precisión utilizando cout?
imprimir float con 2 decimales c++ (11)
Así que obtuve la respuesta a mi última pregunta (no sé por qué no pensé en eso). Estaba imprimiendo un double
usando cout
que se redondeaba cuando no lo esperaba. ¿Cómo puedo hacer que cout
imprima un double
con total precisión?
¿Cómo imprimo un valor
double
con total precisión utilizando cout?
Utilizar hexfloat
o
Usa scientific
y establece 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 proporcionan el valor adecuado necesario. De ahí esta respuesta a una vieja pregunta.
- En que base
Un double
ciertamente se codifica utilizando la 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
?
Un double
es un tipo de punto flotante , no un punto fijo .
No use std::fixed
ya que no se imprime un double
como cualquier cosa menos 0.000...000
. Para el double
grande, imprime muchos dígitos, quizás cientos de informatividad cuestionable.
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, primero use std::scientific
que "escribirá valores de punto flotante en notación científica". Observe 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 totales)?
Una codificación double
con la base binaria 2 codifica la misma precisión entre varias potencias de 2. Esto suele ser de 53 bits.
[1.0 ... 2.0) hay 2 53 double
diferentes,
[2.0 ... 4.0) hay 2 53 double
diferentes,
[4.0 ... 8.0) hay 2 53 double
diferentes,
[8.0 ... 10.0) hay 2/8 * 2 53 double
diferentes.
Sin embargo, si el código se imprime en decimal con N
dígitos significativos, el número de combinaciones [1.0 ... 10.0) es 9/10 * 10 N.
Cualquiera que sea la elección de N
(precisión), no habrá una asignación uno a uno entre el texto double
y el decimal. Si se elige una N
fija, a veces será ligeramente más o menos que lo que realmente se necesita para ciertos valores double
. Podríamos error en muy pocos ( a)
continuación) o demasiados ( b)
continuación).
3 candidatos N
:
a) Use una N
para que al convertir desde texto double
texto lleguemos al mismo texto para todo double
.
std::cout << dbl::digits10 << ''/n'';
// Typical output
15
b) Use una N
para que al convertir de double
texto double
lleguemos al mismo double
para todo double
.
// C++11
std::cout << dbl::max_digits10 << ''/n'';
// Typical output
17
Cuando max_digits10
no está disponible, tenga en cuenta que debido a los atributos de base 2 y base 10, digits10 + 2 <= max_digits10 <= digits10 + 3
, podemos usar digits10 + 3
para asegurar que se imprimen suficientes dígitos decimales.
c) Usa una N
que varíe con el valor.
Esto puede ser útil cuando el código quiere mostrar un texto mínimo ( N == 1
) o el valor exacto de un double
( N == 1000-ish
en el caso de denorm_min
). Sin embargo, dado que esto es "trabajo" y no es probable que sea el objetivo de OP, se dejará de lado.
Normalmente es b) que se utiliza para "imprimir un valor double
con precisión total". Algunas aplicaciones pueden preferir a) error al no proporcionar demasiada información.
Con .scientific
, .precision()
establece el número de dígitos para imprimir después del punto decimal, por lo que se 1 + .precision()
dígitos. El código necesita max_digits10
dígitos totales, por .precision()
se llama a .precision()
con un 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
C similar pregunta
Aquí es cómo mostrar un doble con total precisión:
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::setprecision(precision) << d << std::endl;
Esto muestra:
100.0000000000005
max_digits10 es el número de dígitos que son necesarios para representar de forma única todos los valores dobles distintos. max_digits10 representa el número de dígitos antes y después del punto decimal.
No use set_precision (max_digits10) con std :: fixed.
En notación fija, set_precision () establece el número de dígitos solo después del punto decimal. Esto es incorrecto ya que max_digits10 representa el número de dígitos antes y después del punto decimal.
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::fixed << std::setprecision(precision) << d << std::endl;
Esto muestra un resultado incorrecto:
100.00000000000049738
Aquí está 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 rasgos para todos los tipos de compilación.
Uno de los rasgos para los números de punto flotante (float / double / long double) es el atributo dígitos10. Esto define la precisión (olvido la terminología exacta) de un número de punto flotante en la base 10.
Consulte: http://www.cplusplus.com/reference/std/limits/numeric_limits.html
Para detalles sobre otros atributos.
Con ostream :: precision (int)
cout.precision( numeric_limits<double>::digits10 + 1);
cout << M_PI << ", " << M_E << endl;
rendirá
3.141592653589793, 2.718281828459045
Por qué tiene que decir "+1" No tengo idea, pero el dígito adicional que obtiene es correcto.
El camino de los iostreams es un poco torpe. Prefiero usar boost::lexical_cast
porque calcula la precisión correcta para mí. Y es rápido , tambié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;
Salida:
Pi: 3.14159265358979
Lo más portátil ...
#include <limits>
using std::numeric_limits;
...
cout.precision(numeric_limits<double>::digits10 + 1);
cout << d;
Por precisión total, asumo que la precisión media es suficiente para mostrar la mejor aproximación al valor deseado, pero debe señalarse que el double
se almacena utilizando la representación de base 2 y la base 2 no puede representar algo tan trivial como 1.1
exactamente. La única forma de obtener la precisión total completa del doble real (sin ERROR DE REDONDA DE DESCUENTO) es imprimir los bits binarios (o nybbles hexadecimales). Una forma de hacerlo es escribir el double
en una union
y luego imprimir el valor entero de los bits.
union {
double d;
uint64_t u64;
} x;
x.d = 1.1;
std::cout << std::hex << x.u64;
Esto le dará la precisión 100% precisa del doble ... ¡y será completamente ilegible porque los humanos no pueden leer el formato doble IEEE! Wikipedia tiene un buen escrito sobre cómo interpretar los bits binarios.
En C ++ más reciente, puedes hacer
std::cout << std::hexfloat << 1.1;
Puede establecer la precisión directamente en std::cout
y usar el especificador de formato std::fixed
.
double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;
Puede #include <limits>
para obtener la máxima precisión de flotación o doble.
#include <limits>
typedef std::numeric_limits< double > dbl;
double d = 3.14159265358979;
cout.precision(dbl::max_digits10);
cout << "Pi: " << d << endl;
Utilice std::setprecision
:
std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;
cout es un objeto que tiene un montón de métodos a los que puede llamar para cambiar la precisión y el formato de las cosas impresas.
Hay una operación setprecision (...), pero también puede configurar otras cosas como el ancho de impresión, etc.
Busque cout en la referencia de su IDE.
printf("%.12f", M_PI);
% .12f significa punto flotante, con una precisión de 12 dígitos.