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?

Foi útil?

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.

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

  1. Caso contrário:? fixed ou scientific

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

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

Semelhante C questão

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top