Как проверить, что используется одноточечное (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