Así que obtuve la respuesta a mi última pregunta (no sé por qué no pensé en eso). Estaba imprimiendo un double
uso cout
que se redondeó cuando no lo esperaba. ¿Cómo puedo hacer cout
una impresión double
con total precisión?
332
Así que obtuve la respuesta a mi última pregunta (no sé por qué no pensé en eso). Estaba imprimiendo un double
uso cout
que se redondeó cuando no lo esperaba. ¿Cómo puedo hacer cout
una impresión double
con total precisión?
Puede establecer la precisión directamente std::cout
y utilizar el std::fixed
especificador de formato.
double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;
Puede #include <limits>
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;
fixed
? Condouble h = 6.62606957e-34;
,fixed
me da0.000000000000000
yscientific
salidas6.626069570000000e-34
.cout.precision(numeric_limits<double>::digits10 + 2);
solo obtengo 16 ...max_digits10
para denotar lo mismo. Se corrigió la respuesta para reflejar esto.Uso
std::setprecision
:fuente
std::setprecision (17)
doble, ver los comentarios en la respuesta de @Bill The Lizard.Esto es lo que usaría:
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 coma flotante (flotante / doble / largo doble) es el atributo digits10. Esto define la precisión (se me olvida la terminología exacta) de un número de coma flotante en la base 10.
Consulte: http://www.cplusplus.com/reference/std/limits/numeric_limits.html
Para obtener detalles sobre otros atributos.
fuente
std::setprecision()
:#include <iomanip>
std::numeric_limits<double>
lugar denumberic_limits<double>
1
astd::numeric_limits<double>::digits10
?max_digits10
lugar. Mira esto .max_digits10
, no algo arbitrariodigits10+2
. De lo contrario, en el caso defloat
,long double
,boost::multiprecision::float128
se producirá un error, ya que lo que se necesita+3
en lugar de+2
.La forma de iostreams es un poco torpe. Prefiero usar
boost::lexical_cast
porque calcula la precisión correcta para mí. Y también es rápido .Salida:
fuente
Con total precisión, supongo que la precisión es lo suficientemente mala como para mostrar la mejor aproximación al valor deseado, pero debe señalarse que
double
se almacena utilizando la representación de base 2 y la base 2 no puede representar algo tan trivial como1.1
exactamente. La única forma de obtener la precisión completa del doble real (sin ERROR DE REDONDEO) es imprimir los bits binarios (o nibbles hexadecimales). Una forma de hacerlo es escribirdouble
enunion
ay luego imprimir el valor entero de los bits.¡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 una buena redacción sobre cómo interpretar los bits binarios.
En la versión más reciente de C ++, puedes hacer
fuente
Aquí se explica cómo mostrar un doble con total precisión:
Esto muestra:
max_digits10 es el número de dígitos que son necesarios para representar de forma exclusiva 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.
Esto muestra un resultado incorrecto:
Nota: Se requieren archivos de encabezado
fuente
100.0000000000005
no se representa exactamente como adouble
. (Puede parecer que debería, pero no lo hace, porque se normaliza , es decir, su representación binaria). Para ver esto, trate de:100.0000000000005 - 100
. Nosotros conseguimos4.973799150320701e-13
.Usar
hexfloat
ousar
scientific
y establecer la precisiónDemasiadas 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.
C
double
está ciertamente codificado usando la base 2. Un enfoque directo con C ++ 11 es imprimir usandostd::hexfloat
.Si una salida no decimal es aceptable, hemos terminado.
fixed
oscientific
?A
double
es un tipo de punto flotante , no un punto fijo .No , no utilice
std::fixed
como que no se imprime pequeñadouble
como algo más0.000...000
. Para grandesdouble
, imprime muchos dígitos, quizás cientos de informativos cuestionables.Para imprimir con total precisión, primero use el
std::scientific
cual "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.Un
double
codificado utilizando 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 diferentes
double
,[2.0 ... 4.0) hay 2 53 diferentes
double
,[4.0 ... 8.0) hay 2 53 diferentes
double
,[8.0 ... 10.0) hay 2 / 8 * 2 53 diferentes
double
.Sin embargo, si las impresiones de código 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
N
(precisión) elegida, no habrá un mapeo uno a uno entredouble
y el texto decimal. SiN
se elige un fijo , a veces será un poco más o menos de lo realmente necesario para ciertosdouble
valores. Podríamos cometer un error en muy pocos (a)
abajo) o demasiados (b)
abajo).3 candidato
N
:a) Use un
N
so cuando conviertadouble
texto- -texto llegamos al mismo texto para todosdouble
.b) Use un
N
so cuando convierta dedouble
-texto-double
llegamos a lo mismodouble
para todosdouble
.Cuando
max_digits10
no está disponible, tenga en cuenta que debido a los atributos de base 2 y base 10digits10 + 2 <= max_digits10 <= digits10 + 3
, podemos usardigits10 + 3
para asegurar que se impriman suficientes dígitos decimales.c) Use un
N
que varía con el valor.Esto puede ser útil cuando el código quiere mostrar texto mínimo (
N == 1
) o el valor exacto de adouble
(N == 1000-ish
en el caso dedenorm_min
). Sin embargo, dado que esto es "trabajo" y no es probable que sea el objetivo de OP, se dejará de lado.Generalmente es b) que se usa para "imprimir un
double
valor con total precisión". Algunas aplicaciones pueden preferir a) al 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 que1 + .precision()
se imprimen los dígitos. El código necesitamax_digits10
dígitos totales, por lo que.precision()
se llama con amax_digits10 - 1
.Pregunta C similar
fuente
precision()
establece el número de lugares decimales para el modo científico. Sin especificarscientific
, establece el número total de dígitos, excluyendo el exponente. Aún puede terminar con resultados científicos, dependiendo de su valor numérico, pero también puede obtener menos dígitos de los que especificó. Ejemplo: Loscout.precision(3); cout << 1.7976931348623158e+308; // "1.8e+308"
resultados paraprintf
pueden ser diferentes. Cosas confusas que uno debe tener en cuenta.char buf[DBL_DECIMAL_DIG + 3 + 5]; sprintf(buf, "%.*g", DBL_DECIMAL_DIG, d);
Los caracteres adicionales son para: signo, punto decimal, cero final, e [+ | -], 3 dígitos para el exponente ( DBL_MAX_10_EXP = 308). Por lo tanto, el número total de caracteres requeridos es 25.% .12f significa punto flotante, con precisión de 12 dígitos.
fuente
Lo más portátil ...
fuente
Con ostream :: precision (int)
rendirá
¿Por qué tienes que decir "+1"? No tengo idea, pero el dígito extra que obtienes es correcto.
fuente
Esto mostrará el valor hasta dos decimales después del punto.
Ver aquí: notación de punto fijo
std :: fijo
std :: setprecision
Si está familiarizado con el estándar IEEE para representar los puntos flotantes, sabrá que es imposible mostrar los puntos flotantes con total precisión fuera del alcance del estándar , es decir, siempre resultará en Un redondeo del valor real.
Primero debe verificar si el valor está dentro del alcance , en caso afirmativo, luego use:
std :: defaultfloat
Ese es también el comportamiento predeterminado de
cout
, lo que significa que no lo usa explícitamente.fuente