Подтвердить что ты не робот

Является ли `x!= X` переносным способом тестирования для NaN?

В C вы можете проверить, есть ли double, если NaN использует isnan(x). Однако многие сайты в Интернете, в том числе, например, этот SO ответ говорят, что вы можете просто использовать x!=x вместо этого.

Является ли x!=x в любой спецификации C как метод, который гарантированно проверяет, является ли x NaN? Я не могу найти его сам, и мне бы хотелось, чтобы мой код работал с разными компиляторами.

4b9b3361

Ответ 1

Пожалуйста, обратитесь к нормативному разделу Приложение F: Арифметика с плавающей запятой IEC 60559 стандарта C:

F.1 Введение

Реализация, которая определяет __STDC_IEC_559__, должна соответствовать спецификациям в этом приложении.

Реализации, не определяющие __STDC_IEC_559__, не обязаны соответствовать этим спецификациям.

F.9.3 Реляционные операторы

Выражение x ≠ x истинно, если x является NaN.

Выражение x = x неверно, если x является NaN.

F.3 Операторы и функции

Макрос isnan в <math.h> предоставляет функцию isnan, рекомендованную в Приложении к IEC 60559.

Ответ 2

NaN как единственное значение x со свойством x!=x является гарантией IEEE 754. Является ли это верным тестом для распознавания NaN в C, сводится к тому, насколько точно представление переменных и операций сопоставляется форматам и операциям IEEE 754 в компиляторе (ых), который вы намереваетесь использовать.

Вы должны, в частности, беспокоиться о "избыточной точности" и о том, как с этим справляются компиляторы. Превышение точности - это то, что происходит, когда FPU удобно поддерживает вычисления в более широком формате, чем компилятор хотел бы использовать для типов float и double. В этом случае вычисления могут быть сделаны с большей точностью и округлены до точности типа, когда компилятор чувствует себя непредсказуемым образом.

Стандарт C99 определил способ обработки этой избыточной точности, которая сохранила свойство, что только NaN отличается от самого себя, но долгое время после 1999 года (и даже сейчас, когда авторы компилятора не заботятся), в присутствии избытка точность x != x может быть верна для любой переменной x, которая содержит конечный результат вычисления, если компилятор выбирает округление результата избыточной точности вычисления между оценкой первого x и второй x.

Этот отчет описывает темные времена компиляторов, которые не приложили усилий для реализации C99 (либо потому, что это было не в 1999 году, либо потому, что они 't забота достаточно).

Этот 2008 сообщение описывает, как GCC начал внедрять стандарт C99 для избыточной точности в 2008 году. До этого GCC мог предоставить один со всеми сюрпризов, описанных в вышеупомянутом отчете.

Конечно, если целевая платформа вообще не реализует IEEE 754, значение NaN может даже не существовать или существовать и иметь разные свойства, чем указано в IEEE 754. Общими случаями являются компилятор, который точно реализует IEEE 754 с FLT_EVAL_METHOD, установленным в 0, 1 или 2 (все из которых гарантируют, что x != x iff x - NaN) или компилятор с нестандартной реализацией избыточной точности, где x != x не является надежным тестом для NaN.