Je recommande la solution hexadécimale de @Jens Gustedt : utiliser %a.
Le PO veut "imprimer avec une précision maximale (ou au moins jusqu'à la décimale la plus significative)".
Un exemple simple serait d'imprimer un septième comme dans :
#include <float.h>
int Digs = DECIMAL_DIG;
double OneSeventh = 1.0/7.0;
printf("%.*e\n", Digs, OneSeventh);
// 1.428571428571428492127e-01
Mais creusons un peu plus...
Mathématiquement, la réponse est "0,142857 142857 142857 ...", mais nous utilisons des nombres à virgule flottante de précision finie. Supposons que Binaire double précision IEEE 754 . Ainsi, le OneSeventh = 1.0/7.0
donne la valeur ci-dessous. Sont également indiquées les valeurs représentables précédentes et suivantes double
des nombres à virgule flottante.
OneSeventh before = 0.1428571428571428 214571170656199683435261249542236328125
OneSeventh = 0.1428571428571428 49212692681248881854116916656494140625
OneSeventh after = 0.1428571428571428 769682682968777953647077083587646484375
Impression de la exact représentation décimale d'un double
a des usages limités.
Le C possède 2 familles de macros dans <float.h>
pour nous aider.
Le premier ensemble est le nombre de important les chiffres à imprimer dans une chaîne en décimales de sorte que lors de la numérisation de la chaîne en retour, on retrouve la virgule flottante d'origine. Il y a des exemples avec la spécification C minimum et une valeur échantillon Compilateur C11.
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)
Le deuxième ensemble est le nombre de important chiffres une chaîne de caractères peut être scannée en virgule flottante, puis le FP imprimé, tout en conservant la même présentation de la chaîne de caractères. On peut voir avec la spécification C minimum et une valeur échantillon Compilateur C11. Je crois qu'il était disponible avant C99.
FLT_DIG 6, 6 (float)
DBL_DIG 10, 15 (double)
LDBL_DIG 10, 18 (long double)
Le premier ensemble de macros semble répondre à l'objectif de l'OP, à savoir important digits. Mais cela macro n'est pas toujours disponible.
#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
Le "+ 3" était le point central de ma réponse précédente. Elle était centrée sur le fait que si l'on connaissait la chaîne de conversion aller-retour-FP-chaîne (ensemble #2 macros disponibles C89), comment déterminer les chiffres pour FP-chaîne-FP (ensemble #1 macros disponibles post C89) ? En général, le résultat était d'ajouter 3.
Maintenant, combien de important chiffres à imprimer est connu et piloté via <float.h>
.
Pour imprimer N important chiffres décimaux, on peut utiliser différents formats.
Avec "%e"
le précision le champ est le nombre de chiffres après le chiffre de tête et le point décimal. Ainsi, - 1
est en ordre. Remarque : Ce -1
n'est pas dans la version initiale int Digs = DECIMAL_DIG;
printf("%.*e\n", OP_DBL_Digs - 1, OneSeventh);
// 1.4285714285714285e-01
Avec "%f"
le précision le champ est le nombre de chiffres après le point décimal. Pour un nombre comme OneSeventh/1000000.0
il faudrait OP_DBL_Digs + 6
pour voir tous les important les chiffres.
printf("%.*f\n", OP_DBL_Digs , OneSeventh);
// 0.14285714285714285
printf("%.*f\n", OP_DBL_Digs + 6, OneSeventh/1000000.0);
// 0.00000014285714285714285
Note : Beaucoup ont l'habitude de "%f"
. Cela affiche 6 chiffres après la virgule ; 6 est l'affichage par défaut, et non la précision du nombre.