По крайней мере, один десятичный знак после точки с printf в C

#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;
}