Como faço para imprimir um valor duplo com precisão total utilizando cout?
-
23-08-2019 - |
Pergunta
Assim que eu comecei a resposta à minha última pergunta (I não sei por que eu não tinha pensado nisso). I foi a impressão de uma double
usando cout
que foi arredondado quando eu não estava esperando por isso. Como posso fazer cout
imprimir um double
usando precisão total?
Solução
Você pode definir a precisão diretamente sobre std::cout
e usar o std::fixed
especificador de formato.
double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;
Você pode #include <limits>
para obter a precisão máxima de um float ou double.
#include <limits>
typedef std::numeric_limits< double > dbl;
double d = 3.14159265358979;
cout.precision(dbl::max_digits10);
cout << "Pi: " << d << endl;
Outras dicas
Use std::setprecision
:
std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;
Aqui está o que eu usaria:
std::cout << std::setprecision (std::numeric_limits<double>::digits10 + 1)
<< 3.14159265358979
<< std::endl;
Basicamente, o pacote de limites tem traços para toda a construção em tipos.
Uma das características para números de ponto flutuantes (float / duplo / longo duplo) é o atributo digits10. Isto define a precisão (I esquecer a terminologia exata) de um número de ponto flutuante na base 10.
Veja: http://www.cplusplus.com/reference/std/ limites / numeric_limits.html
Para obter detalhes sobre outros atributos.
A forma iostreams é uma espécie de desajeitado. Eu prefiro usar boost::lexical_cast
porque calcula a precisão certo para mim. E é rápido também.
#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;
Output:
Pi: 3,14159265358979
Aqui está como exibir um casal com precisão total:
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::setprecision(precision) << d << std::endl;
Esta mostra:
100,0000000000005
max_digits10 é o número de dígitos que são necessários para representar de forma única todos os valores duplos distintas. max_digits10 representa o número de dígitos antes e depois do ponto decimal.
Não use set_precision (max_digits10) com std :: fixo.
Em notação fixa, set_precision () define o número de dígitos apenas depois o ponto decimal. Isso é incorreto como max_digits10 representa o número de dígitos antes e depois o ponto decimal.
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::fixed << std::setprecision(precision) << d << std::endl;
Este exibe resultado incorreto:
100,00000000000049738
Nota: Arquivos de cabeçalho necessário
#include <iomanip>
#include <limits>
Por precisão total, presumo precisão média suficiente para mostrar a melhor aproximação para o valor pretendido, mas deve-se salientar que double
são armazenados usando base 2 representação e base 2 não pode representar algo tão trivial como 1.1
exatamente. A única maneira de obter o full-cheia precisão do actual duplo (com NÃO erro de arredondamento) é imprimir os bits binários (ou nybbles hex). Uma maneira de fazer isso é escrever o double
a um union
e, em seguida, imprimir o valor inteiro dos bits.
union {
double d;
uint64_t u64;
} x;
x.d = 1.1;
std::cout << std::hex << x.u64;
Isto lhe dará 100% de precisão exata da dupla ... e ser totalmente ilegível porque os seres humanos não podem ler IEEE formato duplo! Wikipedia tem uma boa escrever sobre como interpretar os bits binários.
Na mais recente C ++, você pode fazer
std::cout << std::hexfloat << 1.1;
Como posso imprimir um valor
double
com total precisão usando cout?
Use hexfloat
ou
uso scientific
e definir a precisão
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
Muitas respostas abordar apenas um de 1) base 2) layout fixo / científica ou 3) de precisão. Muitas respostas com precisão não fornecer o valor adequado necessário. Daí esta resposta a uma pergunta de idade.
- O que base?
A double
é, certamente, codificados usando base 2. Uma abordagem direta com C ++ 11 é imprimir usando std::hexfloat
.
Se uma saída não-decimal é aceitável, estamos a fazer.
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
- Caso contrário:?
fixed
ouscientific
A double
é uma ponto flutuante tipo, não ponto fixo .
não uso std::fixed
como que não consegue imprimir pequena double
como qualquer coisa, mas 0.000...000
. Para grande double
, ele imprime muitos dígitos, talvez centenas de informatividade questionável.
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 com precisão total, a primeira utilização std::scientific
que "escreverá valores de ponto flutuante em notação científica". Observe o padrão de 6 dígitos depois do ponto decimal, uma quantidade insuficiente, é tratado no próximo ponto.
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
- Como muita precisão (quantas total de dígitos)?
A double
codificados usando a base binária 2 codifica a mesma precisão entre as várias potências de 2. Isso é muitas vezes 53 pedaços.
[1,0 ... 2,0) há 2 53 double
diferente,
[2.0 ... 4.0), existem 2 53 double
diferente,
[4,0 ... 8,0) há 2 53 double
diferente,
[8,0 ... 10,0) existem 2/8 * 2 53 double
diferente.
No entanto, se impressões de código decimal com N
algarismos significativos, o número de combinações [1.0 ... 10.0) é 10/9 * 10 N .
Whatever N
(precisão) for escolhida, não haverá um mapeamento um-para-um entre double
e decimal texto. Se um N
fixo é escolhido, às vezes ele vai ser um pouco mais ou menos do que realmente necessário para certos valores double
. Poderíamos erro em muito poucos (a)
abaixo) ou muitos (b)
abaixo).
3 N
candidato:
a) Utilize um N
assim quando conversão de texto-double
-text chegamos ao mesmo texto para todos double
.
std::cout << dbl::digits10 << '\n';
// Typical output
15
b) Use um N
assim ao converter de double
-text-double
chegamos ao mesmo double
para todos double
.
// C++11
std::cout << dbl::max_digits10 << '\n';
// Typical output
17
Quando max_digits10
não está disponível, nota que, devido à base 2 e base de 10 atributos, digits10 + 2 <= max_digits10 <= digits10 + 3
, podemos usar digits10 + 3
para segurar dígitos decimais suficientes são impressos.
c) Use um N
que varia de acordo com o valor.
Isto pode ser útil quando o código quer para exibir o texto mínima (N == 1
) ou o exata ??em> valor de uma double
(N == 1000-ish
no caso de denorm_min
). No entanto, uma vez que este é "trabalho" e não objetivo provável do OP, ele vai ser anulado.
É normalmente b) que é usado para "imprimir um valor double
com total precisão". Algumas aplicações podem preferir a) ao erro em não fornecer muita informação.
Com .scientific
, .precision()
define o número de dígitos para imprimir depois do ponto decimal, de modo dígitos 1 + .precision()
são impressos. necessidades de código max_digits10
dígitos totais assim .precision()
é chamado com um 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
printf("%.12f", M_PI);
%. 12f meios de ponto flutuante, com uma precisão de 12 dígitos.
cout é um objeto que tem um monte de métodos que você pode chamar para alterar a precisão e formatação de material impresso.
Há uma setprecision (...) operação, mas você também pode definir outras coisas como largura de impressão, etc.
Olhe para cima cout em referência do seu IDE.
A maioria portably ...
#include <limits>
using std::numeric_limits;
...
cout.precision(numeric_limits<double>::digits10 + 1);
cout << d;
Com ostream :: precisão (int)
cout.precision( numeric_limits<double>::digits10 + 1);
cout << M_PI << ", " << M_E << endl;
produzirá
3.141592653589793, 2.718281828459045
Por que você tem a dizer "+1" Eu não tenho idéia, mas o dígito extra que você ganha com isso é correto.