Правильный спецификатор формата для double в printf

344

Каков правильный спецификатор формата для double в printf? Это %f или это %lf? Я считаю, что это %f, но я не уверен.

Пример кода

#include <stdio.h>

int main()
{
   double d = 1.4;
   printf("%lf", d); // Is this wrong?
}
  • 14
    Если вы застряли с библиотекой C89, "%lf" не определено; в библиотеках C99 и C11 он определяется как "%f" .
  • 1
    Ваш вариант настолько верен, насколько это возможно. %lf - правильный спецификатор формата для double . Но так стало в C99. До этого нужно было использовать %f .
Теги:
double
printf
format-specifiers

7 ответов

448
Лучший ответ

"%f" - это (или хотя бы один) правильный формат для двойника. Формат float отсутствует, потому что если вы попытаетесь передать float в printf, он будет повышен до double, прежде чем printf получит его 1. "%lf" также допускается в соответствии с текущим стандартом - l указывается как не имеющий эффекта, если следовать спецификатору преобразования f (среди прочих).

Обратите внимание, что это одно место, в котором строки формата printf существенно отличаются от строк формата scanffscanf и т.д.). Для вывода вы передаете значение, которое будет передаваться от float до double при передаче в качестве вариационного параметра. Для ввода вы передаете указатель, который не поддерживается, поэтому вы должны сообщить scanf, хотите ли вы читать float или double, поэтому для scanf, %f означает, что вы хотите read a float и %lf означает, что вы хотите прочитать double (и, для чего стоит, для long double, вы используете %lf для printf или scanf).


<суб > 1. C99, §6.5.2.2/6: "Если выражение, обозначающее вызываемую функцию, имеет тип, который не включает прототип, целые промоакции выполняются для каждого аргумента, а аргументы с типом float повышаются до двух. Они называются рекламными акциями по умолчанию." В С++ формулировка несколько отличается (например, она не использует слово "prototype"), но эффект один и тот же: все вариационные параметры проходят рекламные акции по умолчанию, прежде чем они будут получены функцией. Суб >

  • 4
    Обратите внимание, что g++ отклоняет %lf при компиляции с -Wall -Werror -pedantic : error: ISO C++ does not support the '%lf' gnu_printf format
  • 1
    @kynan: Если так (по крайней мере, если предположить текущую версию g ++), это ошибка в g ++. Для C89 / 90 и C ++ 98/03 разрешение l было расширением. Стандарты C99 / 11 и C ++ 11 требуют, чтобы реализация позволила это.
Показать ещё 4 комментария
53

Учитывая стандарт C99 (а именно проект N1256), правила зависят от function type: fprintf (printf, sprintf,...) или scanf.

Здесь представлены важные части:

Предисловие

Это второе издание отменяет и заменяет первое издание ISO/IEC 9899: 1990 с поправками и исправлениями ISO/IEC 9899/COR1:1994, ISO/IEC 9899/AMD1:1995 и ISO/IEC 9899/COR2: 1996. Основные изменения в предыдущем выпуске:

  • %lf спецификатор преобразования, разрешенный в printf

7.19.6.1 Функция fprintf

7 Модификаторы длины и их значения:

l (ell) Указывает, что (...) не влияет на следующие спецификаторы преобразования a, A, e, E, f, F, g или G.

L Указывает, что для длинного двойного аргумента применяется следующий a, A, e, E, f, F, g или G.

Те же правила, что и для fprintf, применяются для printf, sprintf и подобных функций.

7.19.6.2 Функция fscanf

11 Модификаторы длины и их значения:

l (ell) Указывает, что (...), что следующий спецификатор преобразования a, A, e, E, f, F, g или G применяется к аргументу с указателем типа для double;

L Указывает, что следующие преобразования a, A, e, E, f, F, g или G specifier применяется к аргументу с указателем типа long double.

12 Спецификаторы преобразования и их значения:      a, e, f, g Соответствует необязательно подписанному числу с плавающей запятой, (...)

14 Спецификаторы преобразования A, E, F, G и X также действительны и ведут себя так же, как, соответственно, a, e, f, g и x.

Короче говоря, для fprintf указаны следующие спецификаторы и соответствующие типы:

  • %f → double
  • %lf → длинный двойной.

а для fscanf это:

  • %f → float
  • %lf → double
  • %lf → длинный двойной.
18

Это может быть %f, %g или %e в зависимости от того, как вы хотите форматировать номер. Подробнее см. здесь. Модификатор l требуется в scanf с double, но не в printf.

  • 1
    -1: l (нижний регистр) модификатор для целочисленных типов ( cplusplus.com/reference/clibrary/cstdio/printf ), а L для типов с плавающей запятой. Кроме того, модификатор L ожидает long double , а не простой double .
  • 8
    user470379: Так где же противоречие с моим ответом? Разве я не сказал, что l не требуется в printf для double .
8

Правильный формат printf для double равен %lf точно так же, как вы его использовали. В коде нет ничего плохого.

Формат %lf в printf не поддерживался в старых (pre-C99) версиях языка C, что создавало поверхностную "несогласованность" между спецификаторами формата для double в printf и scanf. Эта поверхностная несогласованность была зафиксирована на C99.

Таким образом, в современном C имеет смысл предпочесть использовать %f с float, %lf с double и %lf с long double последовательно в printf и scanf.

7

%Lf (примечание capital L) является спецификатором формата для удваивается.

Для plain doubles будут выполняться либо %e, %e, %f, %g или %g.

  • 0
    В чем разница между %g и %G ?
  • 0
    @yanpas, нижний / верхний регистр для символа степени, соответственно.
Показать ещё 1 комментарий
-2

Для double вы можете просто использовать %lf или вы можете использовать любое из следующих значений в соответствии с вашими предпочтениями

%e или %e для значений в экспоненциальном формате

%g или %g для нормального или экспоненциального обозначения, в зависимости от того, что более подходит для его величины.

Подробнее здесь Список всех спецификаторов формата в C

-5

Спецификатор формата для double в C % lf, но с printf() нам также необходимо указать диапазон точности, например,

double d=2.284958349586; <br> 
printf("%0.12lf",d);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню