سؤال

ما هي أفضل طريقة لاستخدام NaNs لفي C ++؟

ولقد وجدت std::numeric_limits<double>::quiet_NaN() وstd::numeric_limits<double>::signaling_NaN(). أود أن استخدام signaling_NaN لتمثيل متغير غير مهيأ كما يلي:

double diameter = std::numeric_limits<double>::signaling_NaN();

وهذا، ومع ذلك، وإشارات (يثير استثناء) في مهمة. أريد أن رفع استثناء على الاستخدام، وليس على التعيين.

هل هناك أي طريقة لاستخدام signaling_NaN دون رفع استثناء على التكليف؟ هناك جيدة، بديل محمول لsignaling_NaN التي سترفع استثناء نقطة عائمة عند استخدامها؟

هل كانت مفيدة؟

المحلول

وبعد النظر في هذا بعض أكثر من ذلك، يبدو signaling_NaN لا طائل منه ما هو منصوص عليه. إذا تم تمكين عائم استثناءات نقطة، ثم اصفا إياه بأنه يعد بمثابة تجهيز نان الإشارات، لذلك على الفور بإصدار استثناء. إذا تم تعطيل العائمة الاستثناءات نقطة، ثم معالجة الإشارات نان تلقائيا خفض ترتيب لنان هادئ، لذلك signaling_NaN لا تعمل في اي من الاتجاهين.

كود Menkboy في يعمل، ولكن محاولة استخدام إشارات NaNs ليمتد إلى مشاكل أخرى: ليس هناك طريقة المحمولة لتمكين أو تعطيل العائمة الاستثناءات نقطة (كما ألمح إلى هنا و هنا )، وإذا كنت تعتمد على استثناءات يتم تمكين ، رمز طرف ثالث قد تعطيلها (كما هو موضح هنا ).

وهكذا يبدو مثل موتي في حل هو حقا أفضل خيار.

نصائح أخرى

ما يشير NAN يعني أنه عندما واجه CPU أنها أطلقت إشارة، (ومن هنا جاء الاسم). إذا كنت ترغب في الكشف عن المتغيرات غير مهيأ ثم رفع مستوى التحذير على المترجم الخاص بك عادة بالكشف عن المسارات التي تستخدم القيم uninitalized. إذا تعذر ذلك يمكنك استخدام فئة المجمع الذي يخزن منطقي قائلا إذا تم تهيئة القيمة:

template <class T>
class initialized {
    T t;
    bool is_initialized;
public:
    initialized() : t(T()), is_initialized(false) { }
    initialized(const T& tt) : t(tt), is_initialized(true) { }
    T& operator=(const T& tt) { t = tt; is_initialized = true; return t; }
    operator T&() {
         if (!is_initialized)
             throw std::exception("uninitialized");
         return t; 
   }
};

ويمكنك إرسال نان يشير إلى متغير دون التسبب استثناء مع شيء من هذا القبيل (ملحوظة: لم تختبر)

void set_snan( double &d )
{
    long long *bits = (long long *)&d;
    *bits = 0x7ff0000080000001LL;
}

وانها سوف تعمل معظم الأماكن، ولكن لا، انها ليست 100٪ المحمولة.

حسنا، وتبحث بعد تعريف كل من الهدوء ويشير نان، وأنا لا يمكن أن تجعل حقا أي فرق.

هل يمكن استخدام التعليمات البرمجية التي يتم استخدامها في هذه الوظائف نفسك، وربما يمنع استثناء بهذه الطريقة، ولكن رؤية يست استثناء في تلك الوظيفتين، وأعتقد أنه قد تكون ذات صلة إلى شيء آخر.

إذا كنت تريد تعيين مباشرة نان:

double value = _Nan._Double;

والجواب بسيط: تفعل شيئا مثل هذا في ملف الرأس واستخدامها في كل مكان آخر:

#define NegativeNaN log(-1)

إذا كنت ترغب في القيام ببعض النوع من التلاعب على نحو أفضل كتابة بعض الدالة المجمع موسعة حول exp() مثل extended_exp() وهلم جرا!

ويمكن أن يكون لديك تنفيذ C ++ على API للوصول إلى بيئة نقطة عائمة لاختبار وبعض اضحة العائمة الاستثناءات نقطة. انظر جوابي على سؤال يتصل للحصول على مزيد من المعلومات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top