Eu recomendo a solução hexadecimal @Jens Gustedt: use% a.
OP quer “imprimir com precisão máxima (ou pelo menos até a casa decimal mais significativa)”.
Um exemplo simples seria imprimir um sétimo como em:
#include <float.h>
int Digs = DECIMAL_DIG;
double OneSeventh = 1.0/7.0;
printf("%.*e\n", Digs, OneSeventh);
// 1.428571428571428492127e-01
Mas vamos cavar mais fundo ...
Matematicamente, a resposta é "0,142857 142857 142857 ...", mas estamos usando números de ponto flutuante de precisão finita. Vamos supor que o binário de dupla precisão IEEE 754 . Portanto, os OneSeventh = 1.0/7.0
resultados no valor abaixo. Também são mostrados os double
números de ponto flutuante representáveis anteriores e seguintes .
OneSeventh before = 0.1428571428571428 214571170656199683435261249542236328125
OneSeventh = 0.1428571428571428 49212692681248881854116916656494140625
OneSeventh after = 0.1428571428571428 769682682968777953647077083587646484375
Imprimir a representação decimal exata de umdouble
tem usos limitados.
C tem 2 famílias de macros <float.h>
para nos ajudar.
O primeiro conjunto é o número de dígitos significativos a serem impressos em uma string em decimal, então, ao digitalizar a string de volta, obtemos o ponto flutuante original. Eles são mostrados com o valor mínimo da especificação C e um compilador C11 de amostra .
FLT_DECIMAL_DIG 6, 9 (float) (C11)
DBL_DECIMAL_DIG 10, 17 (double) (C11)
LDBL_DECIMAL_DIG 10, 21 (long double) (C11)
DECIMAL_DIG 10, 21 (widest supported floating type) (C99)
O segundo conjunto é o número de dígitos significativos que uma string pode ser digitalizada em um ponto flutuante e então o FP impresso, ainda mantendo a mesma apresentação da string. Eles são mostrados com o valor mínimo da especificação C e um compilador C11 de amostra . Acredito que disponível pré-C99.
FLT_DIG 6, 6 (float)
DBL_DIG 10, 15 (double)
LDBL_DIG 10, 18 (long double)
O primeiro conjunto de macros parece cumprir a meta do OP de dígitos significativos . Mas essa macro nem sempre está disponível.
#ifdef DBL_DECIMAL_DIG
#define OP_DBL_Digs (DBL_DECIMAL_DIG)
#else
#ifdef DECIMAL_DIG
#define OP_DBL_Digs (DECIMAL_DIG)
#else
#define OP_DBL_Digs (DBL_DIG + 3)
#endif
#endif
O "+ 3" foi o ponto crucial da minha resposta anterior. É centrado em saber se a conversão de ida e volta string-FP-string (conjunto # 2 macros disponíveis C89), como alguém determinaria os dígitos para FP-string-FP (conjunto # 1 macros disponíveis após C89)? Em geral, some 3 foi o resultado.
Agora, quantos dígitos significativos imprimir são conhecidos e direcionados <float.h>
.
Para imprimir N dígitos decimais significativos, pode-se usar vários formatos.
Com "%e"
, o campo de precisão é o número de dígitos após o dígito inicial e o ponto decimal. Então - 1
está em ordem. Nota: Isso -1
não está na inicialint Digs = DECIMAL_DIG;
printf("%.*e\n", OP_DBL_Digs - 1, OneSeventh);
// 1.4285714285714285e-01
Com "%f"
, o campo de precisão é o número de dígitos após o ponto decimal. Para um número como OneSeventh/1000000.0
, seria necessário OP_DBL_Digs + 6
ver todos os dígitos significativos .
printf("%.*f\n", OP_DBL_Digs , OneSeventh);
// 0.14285714285714285
printf("%.*f\n", OP_DBL_Digs + 6, OneSeventh/1000000.0);
// 0.00000014285714285714285
Nota: muitos são usados para "%f"
. Isso exibe 6 dígitos após o ponto decimal; 6 é o padrão de exibição, não a precisão do número.