Ich empfehle @Jens Gustedt hexadezimale Lösung: Verwenden Sie% a.
OP möchte "mit maximaler Genauigkeit (oder zumindest mit der höchstwertigen Dezimalstelle) drucken".
Ein einfaches Beispiel wäre, ein Siebtel wie folgt zu drucken:
#include <float.h>
int Digs = DECIMAL_DIG;
double OneSeventh = 1.0/7.0;
printf("%.*e\n", Digs, OneSeventh);
// 1.428571428571428492127e-01
Aber lasst uns tiefer graben ...
Mathematisch lautet die Antwort "0.142857 142857 142857 ...", aber wir verwenden Gleitkommazahlen mit endlicher Genauigkeit. Nehmen wir an, IEEE 754 Binär mit doppelter Genauigkeit . Also die OneSeventh = 1.0/7.0
Ergebnisse im Wert unten. Ebenfalls gezeigt sind die vorhergehenden und folgenden darstellbaren double
Gleitkommazahlen.
OneSeventh before = 0.1428571428571428 214571170656199683435261249542236328125
OneSeventh = 0.1428571428571428 49212692681248881854116916656494140625
OneSeventh after = 0.1428571428571428 769682682968777953647077083587646484375
Das Drucken der exakten Dezimaldarstellung von a double
hat nur begrenzte Verwendungsmöglichkeiten.
C hat 2 Makrofamilien <float.h>
, die uns helfen.
Der erste Satz gibt die Anzahl der signifikanten Stellen an, die in einer Zeichenfolge in Dezimalzahl gedruckt werden sollen. Wenn Sie die Zeichenfolge zurückscannen, erhalten Sie den ursprünglichen Gleitkommawert. Es werden mit dem Mindestwert der C-Spezifikation und einem Beispiel- C11-Compiler angezeigt .
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)
Der zweite Satz ist die Anzahl der signifikanten Stellen, die eine Zeichenfolge in einen Gleitkommawert gescannt und dann das FP gedruckt werden kann, wobei die gleiche Zeichenfolgenpräsentation beibehalten wird. Es werden mit dem Mindestwert der C-Spezifikation und einem Beispiel- C11-Compiler angezeigt . Ich glaube verfügbar vor C99.
FLT_DIG 6, 6 (float)
DBL_DIG 10, 15 (double)
LDBL_DIG 10, 18 (long double)
Der erste Satz von Makros scheint das OP-Ziel von signifikanten Ziffern zu erfüllen . Dieses Makro ist jedoch nicht immer verfügbar.
#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
Die "+ 3" war der Kern meiner vorherigen Antwort. Wenn man die Round-Trip-Konvertierungszeichenfolge-FP-Zeichenfolge kennt (Set # 2 Makros verfügbar C89), wie würde man die Ziffern für FP-String-FP bestimmen (Set # 1 Makros verfügbar nach C89)? Im Allgemeinen war Add 3 das Ergebnis.
Nun ist bekannt, über wie viele wichtige Ziffern gedruckt werden soll <float.h>
.
Um N signifikante Dezimalstellen zu drucken, kann man verschiedene Formate verwenden.
Mit "%e"
ist das Genauigkeitsfeld die Anzahl der Stellen nach der führenden Ziffer und dem Dezimalpunkt. So - 1
ist es in Ordnung. Hinweis: Dies -1
ist nicht in der Initialeint Digs = DECIMAL_DIG;
printf("%.*e\n", OP_DBL_Digs - 1, OneSeventh);
// 1.4285714285714285e-01
Mit "%f"
ist das Genauigkeitsfeld die Anzahl der Stellen nach dem Dezimalpunkt. Für eine Zahl wie OneSeventh/1000000.0
müsste OP_DBL_Digs + 6
man alle signifikanten Ziffern sehen.
printf("%.*f\n", OP_DBL_Digs , OneSeventh);
// 0.14285714285714285
printf("%.*f\n", OP_DBL_Digs + 6, OneSeventh/1000000.0);
// 0.00000014285714285714285
Hinweis: Viele sind es gewohnt "%f"
. Das zeigt 6 Stellen nach dem Dezimalpunkt an; 6 ist die Standardeinstellung für die Anzeige, nicht die Genauigkeit der Zahl.