سؤال
أثناء كتابة بعض حالات الاختبار ، وبعض الاختبارات تحقق من نتيجة NAN.
حاولت استخدام std::isnan
لكن التأكيد فشل:
Assertion `std::isnan(x)' failed.
بعد طباعة قيمة x
, ، اتضح أنه نان سلبي (-nan
) وهو أمر مقبول تمامًا في حالتي.
بعد محاولة استخدام حقيقة ذلك NaN != NaN
واستخدام assert(x == x)
, ، المترجم يقوم بي "صالح" ويحسن التأكيد بعيدًا.
صنع بلدي isNaN
يتم تحسين الوظيفة أيضًا.
كيف يمكنني التحقق من كل من مساواة NAN و -نان؟
المحلول
هذا محرج.
السبب في أن المترجم (GCC في هذه الحالة) كان يحسن المقارنة و isnan
عاد false
كان بسبب تشغيل شخص ما في فريقي -ffast-math
.
من المستندات:
-ffast-math Sets -fno-math-errno, -funsafe-math-optimizations, -fno-trapping-math, -ffinite-math-only, -fno-rounding-math, -fno-signaling-nans and fcx-limited-range. This option causes the preprocessor macro __FAST_MATH__ to be defined. This option should never be turned on by any -O option since it can result in incorrect output for programs which depend on an exact implementation of IEEE or ISO rules/specifications for math functions.
لاحظ الجملة النهائية - -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 على Snow Leopard. ومع ذلك ، ماذا عن تجربة هذا؟
std::isnan(std::abs(yourNanVariable));
من الواضح أنه لا يمكنني اختباره منذ ذلك الحين std::isnan(-NaN)
هو true
على نظامي.
تعديل: مع -ffast-math
, ، بغض النظر عن -O
Switch ، GCC 4.2.1 على Snow Leopard يعتقد ذلك NAN == NAN
هو true
, ، كما هي NAN == -NAN
. هذا يمكن أن يكسر رمز كارثي. أنصح الخروج -ffast-math
أو على الأقل اختبار لنتائج متطابقة في البناء باستخدام وعدم استخدامه ...
هناك C99 isnan () والتي يجب أن تكون قادرًا على استخدامها.
إذا كان ذلك في تطبيقك لا يعمل بشكل صحيح (أيهما هذا؟) يمكنك تنفيذ خاص بك ، من خلال إعادة PRET_CASTING إلى Long والقيام بسحر IEEE Bit.
يمكنك التحقق من أجزاء الرقم. حدد 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 ".
قد لا يكون هذا محمولًا ، ولكن إذا كنت متأكدًا من platfofm ، فقد يكون مقبولًا. أكثر: 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 على ذلك.