Как минимум один знак после запятой с printf в C - PullRequest
2 голосов
/ 10 апреля 2019

Я ищу способ напечатать число с плавающей запятой в 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 Ответ

4 голосов
/ 10 апреля 2019

Если я правильно понимаю ваш вопрос, вы хотите, чтобы 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

Итак, ваш вопрос должен быть:

Как напечатать число с плавающей запятой спо крайней мере n, но не более p десятичных знаков, исключая конечные нули?

Этого можно достичь, передав 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;
}
...