Consiglio la soluzione esadecimale @Jens Gustedt: usa% a.
OP vuole “stampare con la massima precisione (o almeno fino al decimale più significativo)”.
Un semplice esempio potrebbe essere quello di stampare un settimo come in:
#include <float.h>
int Digs = DECIMAL_DIG;
double OneSeventh = 1.0/7.0;
printf("%.*e\n", Digs, OneSeventh);
// 1.428571428571428492127e-01
Ma andiamo più a fondo ...
Matematicamente, la risposta è "0,142857 142857 142857 ...", ma stiamo usando numeri in virgola mobile a precisione finita. Supponiamo che il binario a doppia precisione IEEE 754 . Quindi i OneSeventh = 1.0/7.0
risultati nel valore di seguito. Sono inoltre mostrati i double
numeri in virgola mobile rappresentabili precedenti e seguenti .
OneSeventh before = 0.1428571428571428 214571170656199683435261249542236328125
OneSeventh = 0.1428571428571428 49212692681248881854116916656494140625
OneSeventh after = 0.1428571428571428 769682682968777953647077083587646484375
La stampa della rappresentazione decimale esatta di a double
ha usi limitati.
C ha 2 famiglie di macro <float.h>
per aiutarci.
Il primo set è il numero di cifre significative da stampare in una stringa in decimale, quindi durante la scansione della stringa, otteniamo il punto mobile originale. Sono mostrati con il valore minimo della specifica C e un compilatore C11 di esempio .
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)
Il secondo set è il numero di cifre significative che una stringa può essere scansionata in un punto mobile e quindi il FP stampato, mantenendo la stessa presentazione della stringa. Sono mostrati con il valore minimo della specifica C e un compilatore C11 di esempio . Credo disponibile prima del C99.
FLT_DIG 6, 6 (float)
DBL_DIG 10, 15 (double)
LDBL_DIG 10, 18 (long double)
La prima serie di macro sembra soddisfare l'obiettivo di OP di cifre significative . Ma quella macro non è sempre disponibile.
#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
Il "+ 3" era il punto cruciale della mia precedente risposta. È incentrato sulla conoscenza della stringa di conversione di andata e ritorno-FP-stringa (set # 2 macro disponibili C89), come si determinano le cifre per FP-string-FP (set # 1 macro disponibili dopo C89)? In generale, aggiungere 3 è stato il risultato.
Ora quante cifre significative stampare sono note e guidate tramite <float.h>
.
Per stampare N cifre decimali significative si possono utilizzare vari formati.
Con "%e"
, il campo di precisione è il numero di cifre dopo la cifra iniziale e il punto decimale. Quindi - 1
è in ordine. Nota: questo -1
non è nell'inizialeint Digs = DECIMAL_DIG;
printf("%.*e\n", OP_DBL_Digs - 1, OneSeventh);
// 1.4285714285714285e-01
Con "%f"
, il campo di precisione è il numero di cifre dopo il punto decimale. Per un numero simile OneSeventh/1000000.0
, bisognerebbe OP_DBL_Digs + 6
vedere tutte le cifre significative .
printf("%.*f\n", OP_DBL_Digs , OneSeventh);
// 0.14285714285714285
printf("%.*f\n", OP_DBL_Digs + 6, OneSeventh/1000000.0);
// 0.00000014285714285714285
Nota: molti sono abituati a "%f"
. Che visualizza 6 cifre dopo il punto decimale; 6 è l'impostazione predefinita di visualizzazione, non la precisione del numero.