Я рекомендую шестнадцатеричное решение @Jens Gustedt: используйте% a.
OP хочет «печатать с максимальной точностью (или, по крайней мере, до самого старшего десятичного числа)».
Простой пример - напечатать одну седьмую, как в:
#include <float.h>
int Digs = DECIMAL_DIG;
double OneSeventh = 1.0/7.0;
printf("%.*e\n", Digs, OneSeventh);
// 1.428571428571428492127e-01
Но давайте копнем глубже ...
Математически ответ будет «0,142857 142857 142857 ...», но мы используем числа с плавающей запятой конечной точности. Предположим, IEEE 754 двоичный код двойной точности . Итак, OneSeventh = 1.0/7.0
результаты в значении ниже. Также показаны предыдущие и последующие представимые double
числа с плавающей запятой.
OneSeventh before = 0.1428571428571428 214571170656199683435261249542236328125
OneSeventh = 0.1428571428571428 49212692681248881854116916656494140625
OneSeventh after = 0.1428571428571428 769682682968777953647077083587646484375
Печать точного десятичного представления a double
имеет ограниченное применение.
В C есть 2 семейства макросов, которые <float.h>
могут нам помочь.
Первый набор - это количество значащих цифр для печати в строке в десятичном формате, поэтому при обратном сканировании строки мы получаем исходную плавающую точку. Они показаны с минимальным значением спецификации C и образцом компилятора 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)
Второй набор - это количество значащих цифр, которые строка может быть отсканирована в число с плавающей запятой, а затем напечатана FP, все еще сохраняя то же представление строки. Они показаны с минимальным значением спецификации C и образцом компилятора C11. Я считаю доступным до C99.
FLT_DIG 6, 6 (float)
DBL_DIG 10, 15 (double)
LDBL_DIG 10, 18 (long double)
Первый набор макросов, похоже, соответствует цели OP по значащим цифрам. Но этот макрос не всегда доступен.
#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
«+3» было сутью моего предыдущего ответа. Он сосредоточен на том, зная, что строка-FP-строка двустороннего преобразования (набор макросов № 2, доступных C89), как можно определить цифры для FP-string-FP (установить макрос № 1, доступный после C89)? В общем, результат прибавил 3.
Теперь известно, сколько значащих цифр нужно напечатать <float.h>
.
Для вывода N значащих десятичных цифр можно использовать различные форматы.
С "%e"
, то точность поле количество цифр после свинцовой цифр и десятичной точки. Так - 1
что по порядку. Примечание: этого -1
нет в начальномint Digs = DECIMAL_DIG;
printf("%.*e\n", OP_DBL_Digs - 1, OneSeventh);
// 1.4285714285714285e-01
С "%f"
, то точность поле количество цифр после десятичной точки. Для такого числа OneSeventh/1000000.0
нужно OP_DBL_Digs + 6
видеть все значащие цифры.
printf("%.*f\n", OP_DBL_Digs , OneSeventh);
// 0.14285714285714285
printf("%.*f\n", OP_DBL_Digs + 6, OneSeventh/1000000.0);
// 0.00000014285714285714285
Примечание: многие используются "%f"
. Это отображает 6 цифр после десятичной точки; По умолчанию отображается 6, а не точность числа.