Je recommande la solution hexadécimale @Jens Gustedt: utilisez% a.
OP 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 plus profondément ...
Mathématiquement, la réponse est "0,142857 142857 142857 ...", mais nous utilisons des nombres à virgule flottante de précision finie. Supposons que le binaire double précision IEEE 754 . Donc, les OneSeventh = 1.0/7.0
résultats dans la valeur ci-dessous. Les double
nombres à virgule flottante représentables précédents et suivants sont également représentés .
OneSeventh before = 0.1428571428571428 214571170656199683435261249542236328125
OneSeventh = 0.1428571428571428 49212692681248881854116916656494140625
OneSeventh after = 0.1428571428571428 769682682968777953647077083587646484375
L'impression de la représentation décimale exacte de a double
a des utilisations limitées.
C a 2 familles de macros <float.h>
pour nous aider.
Le premier ensemble est le nombre de chiffres significatifs à imprimer dans une chaîne en décimal, donc lors de la numérisation de la chaîne, nous obtenons la virgule flottante d'origine. Ils sont affichés avec la valeur minimale de la spécification C et un exemple de 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 chiffres significatifs qu'une chaîne peut être balayée en virgule flottante, puis le FP imprimé, en conservant toujours la même présentation de chaîne. Ils sont affichés avec la valeur minimale de la spécification C et un exemple de compilateur C11. Je crois disponible avant C99.
FLT_DIG 6, 6 (float)
DBL_DIG 10, 15 (double)
LDBL_DIG 10, 18 (long double)
La première série de macros semble atteindre l'objectif de OP significatif chiffres . Mais cette 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 au cœur de ma réponse précédente. Son centré sur la connaissance de la conversion aller-retour string-FP-string (set # 2 macros disponibles C89), comment déterminer les chiffres pour FP-string-FP (set # 1 macros disponibles après C89)? En général, ajouter 3 était le résultat.
Maintenant combien chiffres significatifs à imprimer est connu et piloté <float.h>
.
Pour imprimer N chiffres décimaux significatifs, on peut utiliser différents formats.
Avec "%e"
, le champ de précision correspond au nombre de chiffres après le chiffre principal et la virgule décimale. Il en - 1
va de même. Remarque: ce -1
n'est pas dans leint Digs = DECIMAL_DIG;
printf("%.*e\n", OP_DBL_Digs - 1, OneSeventh);
// 1.4285714285714285e-01
Avec "%f"
, le champ de précision correspond au nombre de chiffres après la virgule décimale. Pour un nombre comme OneSeventh/1000000.0
, il faudrait OP_DBL_Digs + 6
voir tous les chiffres significatifs .
printf("%.*f\n", OP_DBL_Digs , OneSeventh);
// 0.14285714285714285
printf("%.*f\n", OP_DBL_Digs + 6, OneSeventh/1000000.0);
// 0.00000014285714285714285
Remarque: Beaucoup sont habitués à "%f"
. Cela affiche 6 chiffres après la virgule décimale; 6 est la valeur d'affichage par défaut, pas la précision du nombre.