Как проверить, что используется одноточечное (32-разрядное) представление IEEE 754 с плавающей запятой?

Я хочу проверить следующие вещи на моей целевой плате:

  • Является ли 'float' реализованным с IEEE 754 с одноточечной (32-разрядной) переменной с плавающей запятой?
  • Используется ли "double" с переменной IEEE 754 с двойной точностью (64-разрядная) с плавающей запятой?

Какими способами я могу протестировать его с помощью простой программы C.

Ответы

Ответ 1

Простой тест не существует.

В настоящее время подавляющее большинство систем используют форматы IEEE-754 для плавающих точек. Однако большинство реализаций C не полностью соответствуют IEEE 754 (который идентичен IEC 60559) и не устанавливают идентификатор препроцессора __STDC_IEC_559__. В отсутствие этого идентификатора единственным способом определить, соответствует ли реализация C IEEE 754, является одна или комбинация:

  • Прочитайте его документацию.
  • Изучите его исходный код.
  • Протестируйте его (что, конечно, сложно, когда только исчерпывающее тестирование может быть убедительным).

Во многих реализациях C и программных приложениях отклонения от IEEE 754 можно игнорировать или работать: вы можете писать код, как если бы IEEE 754 использовался, и много кода в значительной степени будет работать. Тем не менее, есть множество вещей, которые могут отключить ничего не подозревающего программиста; запись полностью корректного кода с плавающей запятой затруднена даже при выполнении полной спецификации.

Общие отклонения включают в себя:

  • Промежуточная арифметика выполняется с большей точностью, чем номинальный тип. Например, выражения, которые используют значения double, могут быть рассчитаны с точностью long double.
  • sqrt не возвращает правильное округленное значение в каждом случае.
  • Другие подпрограммы математической библиотеки возвращают значения, которые могут быть слегка отключены (несколько ULP) от правильно округленных результатов. (На самом деле, никто не выполнил все математические процедуры, рекомендованные в IEEE 754-2008, с гарантированным правильным округлением и гарантированным сроком выполнения.)
  • Субнормальные числа (крошечные числа рядом с краем формата с плавающей запятой) могут быть преобразованы в ноль вместо обрабатываемых, как указано в IEEE 754.
  • Конверсии между десятичными числами (например, 3.1415926535897932384626433 в исходном коде) и бинарные форматы с плавающей запятой (например, общий формат double, 64-разрядный двоичный код IEEE-754) не всегда округляются правильно, либо в направление преобразования.
  • Поддерживается только круглый-ближайший режим; другие режимы округления, указанные в IEEE 754, не поддерживаются. Или они могут быть доступны для простой арифметики, но для доступа необходимо использовать язык ассемблера, специфичный для машины. Стандартные математические библиотеки (cos, log и т.д.) Редко поддерживают другие режимы округления.

Ответ 2

В C99 вы можете проверить __STDC_IEC_559__:

#ifdef __STDC_IEC_559__
/* using IEEE-754 */
#endif

Это связано с тем, что международный стандарт с плавающей запятой, на который ссылается C99, - IEC 60559: 989 (IEC 559 и IEEE-754 было предыдущим описанием). Отображение с языка C на IEC 60559 является необязательным, но если используется, реализация определяет макрос __STDC_IEC_559__ (Приложение F стандарта C99), поэтому вы можете полностью полагаться на это.

Другой альтернативой является проверка вручную, соответствуют ли значения в float.h, такие как FLT_MAX, FLT_EPSILON, FLT_MAX_10_EXP и т.д. с ограничениями IEEE-754, хотя теоретически может быть другое представление с одинаковые значения.

Ответ 3

Прежде всего, вы можете найти подробную информацию о ISO/IEC/IEEE 60559 (или IEEE 754) в Википедии:

Стандартные типы с плавающей точкой

Как сказал вам F. Goncalvez, макрос __STDC_IEC_559__ предоставляет вам информацию о вашем компиляторе, если он соответствует IEEE 754 или нет.

В дальнейшем мы

Однако вы можете получить дополнительную информацию с помощью макроса FLT_EVAL_METHOD.

Значение этого макроса означает:

  • 0 Все операции и константы оцениваются в диапазоне и точности используемого типа.

  • 1 Операции типов float и double оцениваются в диапазоне и точности double, а long double идет по-своему...

  • 2 Оценки всех типов выполняются в точности и диапазоне long double.

  • -1 Неопределенный

  • Другие отрицательные значения: Реализация определена (зависит от вашего компилятора).

Например, если FLT_EVAL_METHOD == 2 и вы удерживаете результат нескольких вычислений в переменной с плавающей запятой x, тогда все операции и константы вычисляются или обрабатываются в наилучшей точности, то есть long double, но только конечный результат округляется до типа, который x имеет.

Это поведение уменьшает число дискретных ошибок.

Чтобы узнать подробности о типах с плавающей точкой, вы должны следить за постоянными макросами, предоставляемыми стандартным заголовком <float.h>.
Например, см. Эту ссылку:

Характеристики типов с плавающей запятой


В печальном случае, когда ваша реализация не соответствует стандарту IEEE 754, вы можете попробовать найти детали в стандартном заголовке <float.h>, если он существует.
Кроме того, вы должны прочитать документацию своего компилятора.

Например, компилятор GCC объясняет, что делает с плавающей точкой:

Особенности Stadus C99 в GCC