Принтф и длинный двойной

Я использую последнюю версию gcc с Netbeans в Windows. Почему не long double Работа? Это printf спецификатор %lf неправильно?

Код:

#include <stdio.h>

int main(void)
{
    float aboat = 32000.0;
    double abet = 5.32e-5;
    long double dip = 5.32e-5;

    printf("%f can be written %e\n", aboat, aboat);
    printf("%f can be written %e\n", abet, abet);
    printf("%lf can be written %le\n", dip, dip);

    return 0;
}

Выход:

32000.000000 can be written 3.200000e+004
0.000053 can be written 5.320000e-005
-1950228512509697500000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000.000000
can be written 2.725000e+002
Press [Enter] to close the terminal ...

8 ответов

Решение

В дополнение к неправильному модификатору, какой порт gcc для Windows? Mingw использует библиотеку Microsoft C, и я, кажется, помню, что эта библиотека не поддерживает двойной дубль длиной 80 бит (компилятор Microsoft C использует двойной бит длиной 64 бита по разным причинам).

Да - для long doubleнужно использовать %Lf (т. е. верхний регистр 'L').

Из страницы руководства printf:

l (ell) Следующее целочисленное преобразование соответствует аргументу long int или unsigned long int, либо следующее n-преобразование соответствует указателю на аргумент long int, либо следующее c-преобразование соответствует аргументу wint_t, либо следующему s-преобразованию соответствует указателю на аргумент wchar_t.

а также

L A после преобразования a, A, e, E, f, F, g или G соответствует длинному двойному аргументу. (C99 разрешает%LF, но SUSv2 - нет.)

Итак, вы хотите %Le не %le

Редактировать: Некоторые дальнейшие исследования, кажется, показывают, что Mingw использует среду выполнения MSVC/win32 (для таких вещей, как printf) - которая отображает long double на double. Таким образом, смешивание компилятора (такого как gcc), который обеспечивает собственный long double с временем выполнения, которое, кажется, не является беспорядком.

Если вы используете MinGW, проблема в том, что по умолчанию MinGW использует I/O соответственно. функции форматирования из среды выполнения Microsoft C, которая не поддерживает 80-битные числа с плавающей запятой (long double == double в Microsoft земли).

Тем не менее, MinGW также поставляется с набором альтернативных реализаций, которые действительно поддерживают длинные двойные значения. Чтобы использовать их, добавьте к имени функции префикс __mingw_ (например __mingw_printf). В зависимости от характера вашего проекта, вы также можете захотеть глобально #define printf __mingw_printf или использовать -D__USE_MINGW_ANSI_STDIO (который включает версии MinGW всех printfСемейные функции).

У меня была проблема с тестированием длинных пар, и, увы, я натолкнулся на исправление! Вы должны скомпилировать свой проект с -D__USE_MINGW_ANSI_STDIO:

Джейсон Хантли @centurian /home/developer/dependencies/Python-2.7.3/test $ gcc main.c

Джейсон Хантли @centurian /home/developer/dependencies/Python-2.7.3/test $ a.exe c=0,000000

Джейсон Хантли @centurian /home/developer/dependencies/Python-2.7.3/test $ gcc main.c -D__USE_MINGW_ANSI_STDIO

Джейсон Хантли @centurian /home/developer/dependencies/Python-2.7.3/test $ a.exe c=42.000000

Код:

Jason Huntley@centurian /home/developer/dependencies/Python-2.7.3/test
$ cat main.c
#include <stdio.h>

int main(int argc, char **argv)
{
   long double c=42;

   c/3;

   printf("c=%Lf\n",c);

   return 0;
}

В C99 модификатор длины для long double кажется L и не l, man fprintf (или эквивалент для Windows) должен сказать вам для вашей конкретной платформы.

Функции printf и scanf в C/C++ используют библиотеку Microsoft C, и эта библиотека не поддерживает 10-байтовые двойные. Поэтому, когда вы используете функции printf и scanf в своем коде C/C++ для печати длинного двойного значения в качестве вывода и для ввода некоторого ввода в виде длинного двойного значения, это всегда будет давать неправильный результат.

Если вы хотите использовать long double, вы должны использовать функции "__mingw_printf" и "__mingw_scanf" вместо printf и scanf. Он поддерживает 10-байтовый двойной.

Или вы можете определить два макроса следующим образом: " #define printf __mingw_printf " и " #define scanf __mingw_scanf "

Используйте стандартный формат для длинного двойного: %Lf

Как было сказано в других ответах, правильный спецификатор преобразования "%Lf",

Вы можете включить предупреждение о формате, используя -Wformat (или же -Wall, который включает в себя -Wformat) в вызове gcc

$ gcc source.c
$ gcc -Wall source.c
source.c: В функции `main`:
source.c:5: warning: формат "%lf" ожидает тип `double`, но аргумент 2 имеет тип`long double`
source.c:5: warning: формат "%le" ожидает тип `double`, но аргумент 3 имеет тип`long double`
$

Правильный разговор Printf на Java: -

  double pi = Math.PI;

  System.out.format("%f%n", pi);       // -->  "3.141593"
  System.out.format("%.3f%n", pi);     // -->  "3.142"
  System.out.format("%10.3f%n", pi);   // -->  "     3.142"
  System.out.format("%-10.3f%n", pi);  // -->  "3.142"
  System.out.format(Locale.FRANCE,
                    "%-10.4f%n%n", pi); // -->  "3,1416"

  Calendar c = Calendar.getInstance();
  System.out.format("%tB %te, %tY%n", c, c, c); // -->  "May 29, 2006"

  System.out.format("%tl:%tM %tp%n", c, c, c);  // -->  "2:34 am"

  System.out.format("%tD%n", c);    // -->  "05/29/06"
Другие вопросы по тегам