Я ищу способ напечатать число с плавающей запятой в C, которое печатает по меньшей мере с одним десятичным знаком после точки, но все же усекает конечные нули, например.
double x = 5.0;
printf("<some_format>", x);
// should print 5.0, not 5, and not 5.000000
double y = 5.10;
printf("<same_format>", y);
// should print 5.1, not 5.10, and not 5.100000
double x = 5.1230;
printf("<same_format>", z);
// should print 5.123, not 5.1230
Кроме того, определение максимального или фиксированного количества цифр/десятичных знаков — это именно то, чего я пытаюсь избежать.
Кто-нибудь знает об одном формате, который выполняет это с помощью printf
без необходимости прибегать к записи числа в буфер символов, а затем вручную редактировать этот буфер?
стандартные вещи с %g и %f и чтение страницы руководства для printf я ничего не видел по этому поводу.
Это действительно сложно, если не невозможно, поскольку нет никакого способа определить, сколько десятичных знаков действительно имеет значение с плавающей запятой.
Если я правильно понимаю ваш вопрос, вы хотите, чтобы 5.0
печаталось как 5.0
, 5.10
печаталось как 5.1
и 5.15
печаталось как 5.15
...
Не существует простого способа добиться этого с помощью printf
, потому что проблема не так проста: 5.10
представлен в C как double
с дробной частью в двоичном коде, которая является приближением 5.1
, а не точным представлением. Если вы напечатаете его с достаточным количеством знаков после запятой, вы увидите, что он перестанет создавать конечные нули:
printf("%.23f", 5.10) -> 5.09999999999999999991326
Итак, ваш вопрос должен быть:
How to print a floating point number with at least
n
but at mostp
decimals, eliding trailing zeroes?
Этого можно добиться, передав p
в качестве поля точности %f
в sprintf
и запустив цикл для удаления конечных нулей после n
и конечной точки, если n
равно 0
.
Вот пример:
#include <stdio.h>
int print_double(double value, int n, int p) {
char buf[400];
int dot;
int len;
len = snprintf(buf, sizeof buf, "%.*f", p, value);
if (len >= (int)sizeof(buf)) {
printf("value too large: %g\n", value);
return -1;
}
for (dot = 0; dot < len;) {
if (buf[dot++] == '.')
break;
}
while (len - dot > n && buf[len - 1] == '0')
len--;
if (len > 0 && buf[len - 1] == '.')
len--;
buf[len] = '\0';
printf("%s\n", buf);
return len;
}
int main(int argc, char *argv[]) {
print_double(5.0, 1, 2);
print_double(5.1, 1, 2);
print_double(5.15, 1, 2);
return 0;
}
Что вы пробовали? Как ваши попытки сработали или не сработали?