Код может использовать "%.18e"
или "%.18g"
, но вопрос в том, насколько большим должно быть "18"? Является ли 18 лучшим значением? Ответ лежит в DBL_DECIMAL_DIG
.
DBL_DECIMAL_DIG
– это минимальное количество значащих цифр для печати, чтобы гарантировать обход от double
до строки до одного и того же точного double
для всех double
.
Рекомендуется использовать спецификатор формата "%.*e"
.
Обратите внимание, что "18" в "%.18e"
— это количество значащих цифр после десятичной точки. Итак, "%.18e"
печатает 19 значащих цифр.
Используйте printf("%a", x);
для вывода в шестнадцатеричном виде.
Для десятичного вывода:
#include <float.h>
// sign + digit + dp + digits + e + sign + expo + \0
char buf[1 + 1 + 1 + (DBL_DECIMAL_DIG - 1) + 1 + 1 + 5 + 1];
sprintf(buf, "%.*e", DBL_DECIMAL_DIG - 1, x);
Ссылка Спецификатор ширины Printf для поддержания точности значение с плавающей запятой
Число вроде y = 1.0/3.0
, использующее типичный формат double
binary64, должно видеть около 53 десятичные цифры, чтобы увидеть его точное значение. Но многие конечные цифры не нужны для успешного обратного пути.
Теперь мы знаем, какие самые цифры нужно напечатать, используйте приведенную ниже информацию, чтобы избавиться от надоедливых завершающих 0
цифр.
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
char *trim0(double x, char *buf) {
sprintf(buf, "% .*e", DBL_DECIMAL_DIG - 1, x);
if (isfinite(x)) {
char *p = &buf[DBL_DECIMAL_DIG + 1]; // address of last significand digit
char *t;
for (t=p; *t == '0'; t--);
memmove(t+1, p+1, strlen(p+1)+1);
}
return buf;
}
int main(void) {
char buf[1 + 1 + 1 + (DBL_DECIMAL_DIG - 1) + 1 + 1 + 5 + 1];
printf("%s\n", trim0(1.2, buf));
printf("%s\n", trim0(1.0/7, buf));
return 0;
}
Вывод
1.2e+00
1.4285714285714285e-01
03.10.2014