Então, eu recebi a resposta para minha última pergunta (não sei por que não pensei nisso). Eu estava imprimindo um double
uso cout
que era arredondado quando não esperava. Como faço para cout
imprimir double
usando precisão total?
332
fixed
? Comdouble h = 6.62606957e-34;
,fixed
me dá0.000000000000000
escientific
saídas6.626069570000000e-34
.cout.precision(numeric_limits<double>::digits10 + 2);
só consigo 16 ....max_digits10
para denotar o mesmo. Corrigida a resposta para refletir isso.Use
std::setprecision
:fonte
std::setprecision (17)
duplo, veja os comentários na resposta de @Bill The Lizard.Aqui está o que eu usaria:
Basicamente, o pacote de limites possui características para toda a construção em tipos.
Uma das características dos números de ponto flutuante (float / double / long double) é o atributo digits10. Isso define a precisão (esqueço a terminologia exata) de um número de ponto flutuante na base 10.
Consulte: http://www.cplusplus.com/reference/std/limits/numeric_limits.html
Para obter detalhes sobre outros atributos.
fonte
std::setprecision()
:#include <iomanip>
std::numeric_limits<double>
vez denumberic_limits<double>
1
astd::numeric_limits<double>::digits10
?max_digits10
. Veja isso .max_digits10
um pouco arbitráriodigits10+2
. Caso contrário, no caso defloat
,long double
,boost::multiprecision::float128
isso irá falhar, uma vez que você precisa+3
, em vez de+2
.A maneira iostreams é meio desajeitada. Eu prefiro usar
boost::lexical_cast
porque calcula a precisão certa para mim. E é rápido também.Resultado:
fonte
Por precisão total, suponho precisão média suficiente para mostrar a melhor aproximação ao valor pretendido, mas deve-se ressaltar que
double
é armazenado usando a representação da base 2 e a base 2 não pode representar algo tão trivial quanto1.1
exatamente. A única maneira de obter a precisão total do dobro real (com SEM ROUND OFF ERROR) é imprimir os bits binários (ou nybbles hexadecimais). Uma maneira de fazer isso é escreverdouble
paraunion
e depois imprimir o valor inteiro dos bits.Isso lhe dará a precisão 100% exata do duplo ... e será totalmente ilegível porque os humanos não podem ler o formato duplo IEEE! A Wikipedia tem uma boa descrição de como interpretar os bits binários.
No C ++ mais recente, você pode fazer
fonte
Aqui está como exibir um duplo com precisão total:
Isso exibe:
max_digits10 é o número de dígitos necessários para representar exclusivamente todos os valores duplos distintos. max_digits10 representa o número de dígitos antes e depois do ponto decimal.
Não use set_precision (max_digits10) com std :: fixed.
Na notação fixa, set_precision () define o número de dígitos somente após o ponto decimal. Isso está incorreto, pois max_digits10 representa o número de dígitos antes e depois do ponto decimal.
Isso exibe resultado incorreto:
Nota: Arquivos de cabeçalho necessários
fonte
100.0000000000005
não está sendo representado exatamente como adouble
. (Pode parecer que deveria, mas não, porque é normalizado , ou seja, sua representação binária). Para ver isso, tente:100.0000000000005 - 100
. Nós recebemos4.973799150320701e-13
.Use
hexfloat
ouuse
scientific
e defina a precisãoMuitas respostas tratam apenas de 1) base 2) layout fixo / científico ou 3) precisão. Muitas respostas com precisão não fornecem o valor adequado necessário. Daí esta resposta a uma pergunta antiga.
A
double
certamente é codificado usando a base 2. Uma abordagem direta com o C ++ 11 é imprimir usandostd::hexfloat
.Se uma saída não decimal é aceitável, estamos prontos.
fixed
ouscientific
?A
double
é um tipo de ponto flutuante , não ponto fixo .Você não utilizar
std::fixed
como que não consegue imprimir pequenadouble
como qualquer coisa mas0.000...000
. Em geraldouble
, imprime muitos dígitos, talvez centenas de informações questionáveis.Para imprimir com precisão total, use primeiro o
std::scientific
que "escreverá valores de ponto flutuante em notação científica". Observe que o padrão de 6 dígitos após o ponto decimal, uma quantidade insuficiente, é tratado no próximo ponto.Um
double
codificado usando a base binária 2 codifica a mesma precisão entre várias potências de 2. Isso geralmente é 53 bits.[1,0 ... 2,0) existem 2 53 diferentes
double
,[2,0 ... 4,0) existem 2 53 diferentes
double
,[4,0 ... 8,0) existem 2 53 diferentes
double
,[8,0 ... 10,0) existem 2 / 8 * 2 53 diferentes
double
.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 .Qualquer que seja
N
(precisão) escolhida, não haverá um mapeamento individual entredouble
e texto decimal. Se um fixoN
for escolhido, algumas vezes será um pouco mais ou menos do que o necessário para determinadosdouble
valores. Podemos errar em muito poucos (a)
abaixo) ou muitos (b)
abaixo).3 candidato
N
:a) Use um
N
modo quando, ao converter de texto emdouble
texto, chegamos ao mesmo texto para todosdouble
.b) Use um
N
so ao converter dedouble
-text-double
chegamos ao mesmodouble
para todosdouble
.Quando
max_digits10
não estiver disponível, observe que, devido aos atributos da base 2 e da base 10digits10 + 2 <= max_digits10 <= digits10 + 3
, podemos usardigits10 + 3
para garantir que dígitos decimais suficientes sejam impressos.c) Use um
N
que varia com o valor.Isso pode ser útil quando o código deseja exibir o mínimo de texto (
N == 1
) ou o valor exato de adouble
(N == 1000-ish
no caso dedenorm_min
). No entanto, como esse é "trabalho" e provavelmente não é o objetivo do OP, será deixado de lado.Geralmente é b) usado para "imprimir um
double
valor com precisão total". Alguns aplicativos podem preferir: a) erro ao não fornecer muitas informações.Com
.scientific
,.precision()
define o número de dígitos a serem impressos após o ponto decimal, para que os1 + .precision()
dígitos sejam impressos. O código precisa demax_digits10
dígitos totais, então.precision()
é chamado com amax_digits10 - 1
.Pergunta C semelhante
fonte
precision()
definir o número de casas decimais para o modo científico. Sem especificarscientific
, ele define o número total de dígitos, excluindo o expoente. Você ainda pode ter resultados científicos, dependendo do valor numérico, mas também poderá obter menos dígitos do que o especificado. Exemplo: oscout.precision(3); cout << 1.7976931348623158e+308; // "1.8e+308"
resultados paraprintf
podem ser diferentes. Coisas confusas que devemos ter em mente.char buf[DBL_DECIMAL_DIG + 3 + 5]; sprintf(buf, "%.*g", DBL_DECIMAL_DIG, d);
Os caracteres extras são para: sinal, ponto decimal, zero à direita, e [+ | -], 3 dígitos para o expoente ( DBL_MAX_10_EXP = 308). Portanto, o número total de caracteres necessários é 25.% .12f significa ponto flutuante, com precisão de 12 dígitos.
fonte
Mais portàvel ...
fonte
Com ostream :: precision (int)
vai render
Por que você tem que dizer "+1" Eu não tenho idéia, mas o dígito extra que você obtém está correto.
fonte
Isso mostrará o valor até duas casas decimais após o ponto.
Veja aqui: Notação de ponto fixo
std :: fixed
std :: setprecision
Se você estiver familiarizado com o padrão IEEE para representar os pontos flutuantes, saberia que é impossível mostrar pontos flutuantes com precisão total fora do escopo do padrão , ou seja, isso sempre resultará em um arredondamento do valor real.
Você precisa primeiro verificar se o valor está dentro do escopo ; se sim, use:
std :: defaultfloat
Esse também é o comportamento padrão de
cout
, o que significa que você não o usa explicitamente.fonte