Правильный спецификатор формата для double в printf - PullRequest
428 голосов
/ 24 ноября 2010

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

Пример кода

#include <stdio.h>

int main()
{
   double d = 1.4;
   printf("%lf", d); // Is this wrong?
}

Ответы [ 6 ]

552 голосов
/ 24 ноября 2010

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

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


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

58 голосов
/ 29 апреля 2012

Учитывая стандарт C99 (а именно, черновик N1256 ), правила зависят от типа функции: 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Спецификатор ion применяется к аргументу с указателем типа long long.

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

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

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

  • %f -> double
  • %Lf -> long double.

и для fscanf это:

  • %f -> float
  • %lf-> двойной
  • %Lf -> длинный двойной.
19 голосов
/ 24 ноября 2010

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

9 голосов
/ 07 мая 2016

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

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

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

8 голосов
/ 24 ноября 2010

%Lf (обратите внимание на заглавную L) - это спецификатор формата для длинных двойных чисел .

Для простого doubles подойдут %e, %E, %f, %g или %G.

0 голосов
/ 21 мая 2015

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

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

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

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

...