Как проверить, что используется представление с плавающей точкой одинарной (32-битной) точности IEEE 754?
Я хочу проверить следующие вещи на моей целевой плате:
- Реализуется ли 'float' с помощью переменной с плавающей точкой одинарной (32-битной) точности IEEE 754?
- Реализуется ли double с помощью переменной с плавающей точкой двойной точности (64-разрядной) IEEE 754?
Как можно проверить это с помощью простой программы на Си?
4 ответа
Простого теста не существует.
Подавляющее большинство систем сегодня используют форматы 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
формат, IEEE-754 (64-разрядный двоичный файл) не всегда округляются правильно, в любом направлении преобразования. - Поддерживается только режим округления до ближайшего; другие режимы округления, указанные в IEEE 754, не поддерживаются. Или они могут быть доступны для простой арифметики, но требуют доступа к машинному языку для доступа. Стандартные математические библиотеки (
cos
,log
и так далее) редко поддерживают другие режимы округления.
В C99 вы можете проверить __STDC_IEC_559__
:
#ifdef __STDC_IEC_559__
/* using IEEE-754 */
#endif
Это связано с тем, что международным стандартом с плавающей запятой, на который ссылается C99, является МЭК 60559:989 (предыдущее описание - МЭК 559 и IEEE-754). Отображение из языка C в IEC 60559 является необязательным, но если используется, реализация определяет макрос __STDC_IEC_559__
(Приложение F к стандарту C99), так что вы можете полностью положиться на это.
Другой альтернативой является ручная проверка, если значения в float.h
, такие как FLT_MAX
, FLT_EPSILON
, FLT_MAX_10_EXP
и т. д. соответствуют ограничениям IEEE-754, хотя теоретически может быть другое представление с такими же значениями.
Прежде всего, вы можете найти подробную информацию о ISO/IEC/IEEE 60559 (или IEEE 754) в Википедии:
Стандартные типы с плавающей точкой
Как сказал вам Ф. Гонсалвес, макрос __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 объясняет, что делает с плавающей запятой:
Нет, Стандарт C18, с. 373 указывает, что IEC 60559 используется для
float
,
double
...
Как вы думаете, почему используется IEEE 754?