Вопрос

При написании некоторых тестовых примеров некоторые тесты проверяют результат NaN.

Я попробовал использовать std::isnan но утверждение не выполняется:

Assertion `std::isnan(x)' failed.

После печати значения x, оказалось, что это отрицательный NaN (-nan), что в моем случае вполне приемлемо.

После попытки использовать тот факт, что NaN != NaN и используя assert(x == x), компилятор оказывает мне «одолжение» и оптимизирует утверждение.

Делаю свой собственный isNaN функция также оптимизируется.

Как я могу проверить равенство NaN и -НаН?

Это было полезно?

Решение

Это раздражительно.

Причина компилятора (GCC в этом случае) оптимизировала сравнение и isnan вернулся false было потому, что кто-то в моей команде включил -ffast-math.

Из документов:

-FAST-математические наборы -FNO-MATH-ERRNO, -FUNSAFE-MATH-ОПТИМАТИЗАЦИИ, -ФНО-ТОЛОВЫЕ, ТОЛЬКО-ТЛИН-ТОЛЬКО-ТОЛЬКО-ТОЛЬКО-ТОЛЬКО-ТОЛЬКОМУКИ, -Наспинги-Округления, -FNO-NANS и FCX Limited -спектр. Эта опция приводит к определению препроцессора __Fast_Math__. Эта опция никогда не должна быть включена в любой опция -O, поскольку она может привести к неправильному выходу для программ, которые зависят от точной реализации правил / спецификаций IEEE или ISO для математических функций.

Обратите внимание на окончательное предложение - -ffast-math небезопасно.

Другие советы

isnan() ожидается, что будет неопределенное поведение с -ffast-math.

Это то, что я использую в моем тестовом номере:

#if defined __FAST_MATH__
#   undef isnan
#endif
#if !defined isnan
#   define isnan isnan
#   include <stdint.h>
static inline int isnan(float f)
{
    union { float f; uint32_t x; } u = { f };
    return (u.x << 1) > 0xff000000u;
}
#endif

Это похоже на ошибку в реализации вашей библиотеки isnan() мне. Здесь работает нормально, на GCC 4.2.1 на снежном леопарде. Тем не менее, как насчет попробовать это?

std::isnan(std::abs(yourNanVariable));

Очевидно, я не могу это проверить, так как std::isnan(-NaN) является true в моей системе.

РЕДАКТИРОВАТЬ: С участием -ffast-math, независимо от -O Переключатель, GCC 4.2.1 на снежном леопарде думает, что NAN == NAN является true, как есть NAN == -NAN. Отказ Это может потенциально сломать код катастрофически. Я бы посоветовал уйти -ffast-math Или, по крайней мере, тестирование на одинаковые результаты в сборках, использующих и не используя его ...

Есть C99 Isnan (), который вы должны быть в состоянии использовать.

Если в вашей реализации он не работает правильно (какой из них что?) Вы можете реализовать свои собственные, ReinterPret_casting в долгое время и делать бит-магию IEEE.

Вы можете проверить биты числа.IEEE 754 определил маску для NaN:

  • Сигнальный NaN представлен любой битовой комбинацией между X'7F80 0001' и X'7FBF FFFF' или между X'FF80 0001' и X'FFBF FFFF'.
  • Тихий NaN представлен любой битовой комбинацией между X'7FC0 0000' и X'7FFF FFFF' или между X'FFC0 0000' и X'FFFF FFFF'.

Это может быть непереносимо, но если вы уверены в своей платформе, это может быть приемлемо.Более: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlf101l.doc/xlfopg/fpieee.htm

Это основано на статье Википедии, размещенной в комментариях. Обратите внимание, что это совсем непроверено - это должно дать вам представление о том, что вы можете сделать, хотя.

bool reallyIsNan(float x)
{
    //Assumes sizeof(float) == sizeof(int)
    int intIzedX = *(reinterpret_cast<int *>(&x));
    int clearAllNonNanBits = intIzedX & 0x7F800000;
    return clearAllNonNanBits == 0x7F800000;
}

Редактировать: Я действительно думаю, что вы должны подумать о том, чтобы подать ошибку с помощью Glibc ребята на этом одном.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top