#c #string #printing #terminal #printf
#c #строка #печать #терминал #printf
Вопрос:
Я ищу способ напечатать число с плавающей запятой на 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
без необходимости прибегать к записи числа в буфер символов, а затем вручную редактировать этот буфер?
Комментарии:
1. Что вы пробовали? Как ваши попытки сработали или не сработали?
2. стандартный материал с%g и%f и чтение страницы руководства для printf, я ничего не видел по этому вопросу.
3. Это действительно сложно, если не невозможно, поскольку на самом деле нет способа определить, сколько десятичных знаков действительно имеет значение с плавающей запятой.
Ответ №1:
Если я правильно понял ваш вопрос, вы хотите 5.0
напечатать как 5.0
, 5.10
напечатать как 5.1
и 5.15
напечатать как 5.15
…
Простого способа добиться этого не существует printf
, потому что проблема не так проста: 5.10
представлена в C как a double
с двоичной кодированной дробной частью, которая является приближением 5.1
, а не точным представлением. Если вы напечатаете его с достаточным количеством десятичных знаков, вы увидите, что он перестает выдавать конечные нули:
printf("%.23f", 5.10) -> 5.09999999999999999991326
Итак, ваш вопрос должен быть:
Как напечатать число с плавающей запятой, по крайней мере
n
, но не болееp
десятичных знаков, исключая конечные нули?
Этого можно достичь, передав p
в качестве поля точности %f
in 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: %gn", value);
return -1;
}
for (dot = 0; dot < len;) {
if (buf[dot ] == '.')
break;
}
while (len - dot > n amp;amp; buf[len - 1] == '0')
len--;
if (len > 0 amp;amp; buf[len - 1] == '.')
len--;
buf[len] = '';
printf("%sn", 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;
}