ما هو الأساس المنطقي لجميع المقارنات التي تعود خاطئة لقيم NANE754؟

StackOverflow https://stackoverflow.com/questions/1565164

سؤال

لماذا تتصرف مقارنات قيم النان بشكل مختلف عن جميع القيم الأخرى؟ وهذا يعني أن جميع المقارنات مع المشغلين == ، <= ،> = ، <،> حيث يتم إرجاع إحدى القيم أو كلتا القيمتين كاذبة ، على عكس سلوك جميع القيم الأخرى.

أفترض أن هذا يبسط الحسابات العددية بطريقة ما ، لكنني لم أتمكن من العثور على سبب محدد صراحة ، ولا حتى في ملاحظات المحاضرة حول حالة IEEE 754 بقلم كاهان الذي يناقش قرارات التصميم الأخرى بالتفصيل.

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

تعديل:يجادل جميع الإجابات حتى الآن أنه لا معنى لها مقارنة NANS.

أوافق ، لكن هذا لا يعني أن الإجابة الصحيحة خاطئة ، بل إنها ستكون غير متوفرة (NAB) ، والتي لحسن الحظ غير موجودة.

لذا فإن اختيار إرجاع صحيح أو خطأ للمقارنات هو في رأيي بشكل تعسفي ، وبالنسبة لمعالجة البيانات العامة سيكون مفيدًا إذا طاعة القوانين المعتادة (انعكاس == ، بضع ثلاثية <، == ،>) ، خشية أن تكون هياكل البيانات التي تعتمد على هذه القوانين تصبح مرتبكة.

لذلك أنا أطلب بعض الاستفادة الملموسة لكسر هذه القوانين ، وليس فقط التفكير الفلسفي.

تحرير 2:أعتقد أنني أفهم الآن لماذا سيكون صنع NAN Maximal فكرة سيئة ، فهي تعبث في حساب الحدود العليا.

قد يكون من المرغوب فيه NAN! = NAN لتجنب اكتشاف التقارب في حلقة مثل

while (x != oldX) {
    oldX = x;
    x = better_approximation(x);
}

ومع ذلك ، ينبغي كتابة أفضل من خلال مقارنة الفرق المطلق مع حد صغير. لذلك IMHO هذه حجة ضعيفة نسبيا لكسر الانعكاسية في نان.

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

المحلول

كنت عضوًا في لجنة IEEE-754 ، سأحاول المساعدة في توضيح الأشياء قليلاً.

أولاً ، لا تعد أرقام النقطة العائمة أرقامًا حقيقية ، ولا ترضي الحساب العائم على بديهيات الحساب الحقيقي. لا يمثل بضع الثلاثية الخاصية الخاصية الوحيدة للحساب الحقيقي الذي لا يحمل العوامات ، ولا حتى الأهم. علي سبيل المثال:

  • الإضافة ليست مرتبطة.
  • القانون التوزيعي لا يحمل.
  • هناك أرقام نقطة عائمة دون عكس.

أنا يمكن أن تستمر. لا يمكن تحديد نوع الحساب ثابت الحجم الذي يرضي الكل من خصائص الحساب الحقيقي الذي نعرفه ونحبه. يتعين على اللجنة 754 أن تقرر الانحناء أو كسر بعضها. هذا يسترشد ببعض المبادئ البسيطة جدا:

  1. عندما نستطيع ، فإننا نطابق سلوك الحساب الحقيقي.
  2. عندما لا نستطيع ذلك ، نحاول أن نجعل الانتهاكات يمكن التنبؤ بها وسهلة التشخيص قدر الإمكان.

فيما يتعلق بتعليقك "هذا لا يعني أن الإجابة الصحيحة خاطئة" ، هذا خطأ. المسند (y < x) يسأل ما إذا كان y اقل من x. لو y هو نان ، إذن هو ليس أقل من أي قيمة نقطة عائمة x, ، لذلك الجواب خاطئ بالضرورة.

ذكرت أن بضع ثلاثي الأبعاد لا يحتفظ بقيم الفاصلة العائمة. ومع ذلك ، هناك خاصية مماثلة تحمل. البند 5.11 ، الفقرة 2 من معيار 754-2008:

أربع علاقات متبادلة ممكنة: أقل من ، متساوية ، أكبر من ، وغير مرتبة. تنشأ الحالة الأخيرة عندما يكون المعامل على الأقل نان. يجب على كل نان مقارنة غير المرتبة بكل شيء ، بما في ذلك نفسه.

فيما يتعلق بكتابة رمز إضافي للتعامل مع NANS ، من الممكن عادة (وإن لم يكن سهلاً دائمًا) هيكل الكود الخاص بك بطريقة تسير فيها NANS بشكل صحيح ، ولكن هذا ليس هو الحال دائمًا. عندما لا يكون الأمر كذلك ، قد يكون بعض التعليمات البرمجية الإضافية ضرورية ، ولكن هذا سعر ضئيل لدفعه مقابل الراحة التي جلبها الإغلاق الجبري إلى الحساب العائم.


إضافة: جادل العديد من المعلقين بأنه سيكون من المفيد الحفاظ على انعكاسية المساواة والاستئصال الثلاثية على أساس أن تبني NAN! = نان لا يبدو أنه يحافظ على أي بديهية مألوفة. أعترف ببعض التعاطف مع وجهة النظر هذه ، لذلك اعتقدت أنني سأعيد النظر في هذه الإجابة وأقدم المزيد من السياق.

ما أفهمه من التحدث إلى كاهان هو أن نان! = نان نشأ من بين اعتبارات براغماتية:

  • الذي - التي x == y يجب أن تكون مكافئة ل x - y == 0 كلما كان ذلك ممكنًا (إلى جانب كونه نظرية للحساب الحقيقي ، فإن هذا يجعل تنفيذ الأجهزة للمقارنة أكثر كفاءة في المساحة ، والتي كانت ذات أهمية قصوى في الوقت الذي تم فيه تطوير المعيار-ومع ذلك ، لاحظ أن هذا ينتهك لـ x = y = y = اللانهاية ، لذلك ليس سببًا رائعًا من تلقاء نفسه ؛ كان يمكن أن يكون عازمة بشكل معقول (x - y == 0) or (x and y are both NaN)).

  • الأهم من ذلك ، لم يكن هناك isnan( ) المسند في الوقت الذي تم فيه إضفاء الطابع الرسمي على NAN في الحساب 8087 ؛ كان من الضروري تزويد المبرمجين بوسائل مريحة وفعالة لاكتشاف قيم NAN التي لا تعتمد على لغات البرمجة التي توفر شيئًا مثل isnan( ) والتي يمكن أن تستغرق سنوات عديدة. سأقتبس من كتابة كاهان حول هذا الموضوع:

لم يكن هناك طريقة للتخلص من NANS ، سيكونون غير مجديين مثل غير المحتملين على كرايز ؛ بمجرد مواجهة المرء ، من الأفضل إيقاف الحساب بدلاً من الاستمرار لفترة غير محددة إلى نتيجة غير محددة. هذا هو السبب في أن بعض العمليات على NANS يجب أن تقدم نتائج غير نان. ما هي العمليات؟ ... تتوقع الاستثناءات C "x == x" و "x! = x" ، والتي هي على التوالي 1 و 0 لكل رقم غير محدود أو محدود x ولكن عكس إذا لم يكن x رقمًا (NAN) ؛ توفر هذه التمييز غير الاستثنائي البسيط الوحيد بين NANS والأرقام في اللغات التي تفتقر إلى كلمة لـ NAN و isnan المسند.

لاحظ أن هذا هو المنطق أيضًا الذي يستبعد إرجاع شيء مثل "غير بوليان". ربما كانت هذه البراغماتية في غير محله ، ويجب أن يكون المعيار مطلوبًا isnan( ), ، لكن ذلك كان من شأنه أن يجعل NAN من المستحيل تقريبًا استخدامه بكفاءة وسهولة لعدة سنوات بينما ينتظر العالم اعتماد لغة البرمجة. لست مقتنعا بأنه كان من شأنه أن يكون مفاضلة معقولة.

أن تكون صريحًا: لن تتغير نتيجة NAN == NAN الآن. من الأفضل أن تتعلم العيش معها بدلاً من الشكوى على الإنترنت. إذا كنت تريد القول بأن علاقة الطلب المناسبة للحاويات يجب ايضا موجود ، أوصي بالدعوة إلى تنفيذ لغة البرمجة المفضلة لديك totalOrder مسند موحد في IEEE-754 (2008). حقيقة أنه لم يتحدث بالفعل عن صحة قلق كاهان الذي حفز الوضع الحالي.

نصائح أخرى

يمكن التفكير في نان كدولة/رقم غير محدد. على غرار مفهوم 0/0 كونه غير محدد أو SQRT (-3) (في نظام الأرقام الحقيقي حيث تعيش النقطة العائمة).

يتم استخدام NAN كنوع من العناصر النائبة لهذه الحالة غير المحددة. من الناحية الرياضية ، غير المحددة لا تساوي غير محددة. لا يمكنك القول أن القيمة غير المحددة أكبر أو أقل من قيمة أخرى غير محددة. لذلك جميع المقارنات تعود خاطئة.

هذا السلوك مفيد أيضًا في الحالات التي تقارن فيها SQRT (-3) إلى SQRT (-2). كلاهما يعيدون نان لكنهما غير مكافئين على الرغم من أنهما يعيدون نفس القيمة. لذلك ، فإن المساواة دائمًا ما تعود خاطئة عند التعامل مع NAN هي السلوك المطلوب.

لرمي تشبيه آخر. إذا قمت بتسليم صندوقين ، وأخبرك أن أيا منهما لا يحتوي على تفاحة ، فهل ستخبرني أن الصناديق تحتوي على نفس الشيء؟

لا تحتوي NAN على أي معلومات حول ما هو شيء ما ، فقط ما ليس عليه. لذلك لا يمكن أن يقال هذه العناصر بالتأكيد على قدم المساواة.

من مقالة ويكيبيديا نان, ، قد تسبب الممارسات التالية NANS:

  • جميع العمليات الرياضية> مع NAN كمعامل واحد على الأقل
  • الانقسامات 0/0 ، ∞/∞ ، ∞/-∞ ، -∞/∞ ، و -∞/-∞
  • مضاعفات 0 × ∞ و 0 × -∞
  • الإضافات ∞ + (-∞) ، (-∞) + ∞ والطرح المكافئ.
  • تطبيق وظيفة على الوسائط خارج نطاقها ، بما في ذلك أخذ الجذر التربيعي للرقم السالب ، أو أخذ اللوغاريتم على رقم سالب أو جيب التمام من رقم أقل من -1 أو أكبر من +1.

نظرًا لعدم وجود طريقة لمعرفة أي من هذه العمليات التي خلقت النان ، لا توجد طريقة لمقارنتها أمر منطقي.

لا أعرف الأساس المنطقي للتصميم ، لكن إليك مقتطف من معيار IEEE 754-1985:

"يجب أن يكون من الممكن مقارنة أرقام النقطة العائمة في جميع التنسيقات المدعومة ، حتى لو اختلت تنسيقات المعامل . آخر حالة تنشأ عندما يكون المعامل على الأقل هو نان. كل نان يقارن غير مرتبة مع كل شيء ، بما في ذلك نفسه. "

يبدو الأمر غريبًا فقط لأن معظم بيئات البرمجة التي تسمح لـ NAN لا تسمح أيضًا بمنطق 3 قيمة. إذا رميت المنطق ذو القيمة 3 في المزيج ، يصبح متسقًا:

  • (2.7 == 2.7) = صحيح
  • (2.7 == 2.6) = خطأ
  • (2.7 == nan) = غير معروف
  • (nan == nan) = غير معروف

حتى .NET لا يوفر ملف bool? operator==(double v1, double v2) المشغل ، لذلك ما زلت عالقًا مع السخيفة (NaN == NaN) = false نتيجة.

أظن أن NAN (وليس رقمًا) يعني بالضبط أن هذا ليس رقمًا وبالتالي فإن مقارنته لا معنى له حقًا.

إنه يشبه إلى حد ما الحساب في SQL مع null المعاملات: جميعها تؤدي إلى null.

تقارن المقارنات لأرقام النقاط العائمة القيم الرقمية. وبالتالي ، لا يمكن استخدامها للقيم غير الرقمية. لذلك لا يمكن مقارنة نان بالمعنى الرقمي.

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

قد تفكر في اختبار واستبدال NANS الخاص بك بـ +inf إذا كنت تريد أن يتصرف مثل +inf.

NAN هو مثيل جديد ضمني (من نوع خاص من خطأ وقت التشغيل). هذا يعني NaN !== NaN لنفس السبب new Error !== new Error;

وتأخذ في الاعتبار أن مثل هذه الضمني /a/ !== /a/ وهو مجرد بناء جملة السكر new RegExp('a') !== new RegExp('a')

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

لأن الرياضيات هي المجال الذي "موجود فقط". في الحوسبة يجب عليك تهيئة تلك الأرقام و احتفظ حالتهم حسب احتياجاتك. في تلك الأيام الخوالي ، عملت تهيئة الذاكرة بالطرق التي لا يمكنك الاعتماد عليها أبدًا. لا يمكنك السماح لنفسك بالتفكير في هذا "أوه ، سيتم تهيئة ذلك باستخدام 0xCD طوال الوقت ، لن ينكسر algo الخاص بي".

لذلك تحتاج عدم الخلط المذيبات لزجة بما فيه الكفاية لعدم السماح لخوارزميةك بالامتصاص والكسر. الخوارزميات الجيدة التي تنطوي على الأرقام ستعمل في الغالب مع العلاقات وتلك لو() سيتم حذف العلاقات.

هذا مجرد شحوم يمكنك وضعها في متغير جديد في الإنشاء ، بدلاً من برمجة الجحيم العشوائي من ذاكرة الكمبيوتر. وخوارزميةك مهما كانت ، لن تنكسر.

بعد ذلك ، عندما لا تزال تكتشف فجأة أن خوارزميةك تنتج NANS ، فمن الممكن تنظيفها ، والنظر في كل فرع في وقت واحد. مرة أخرى ، تساعد القاعدة "الخاطئة دائمًا" كثيرًا في هذا.

بالنسبة لي ، أسهل طريقة لشرح ذلك هي:

لدي شيء وإذا لم يكن تفاحة ، فهل هي برتقالية؟

لا يمكنك مقارنة NAN بشيء آخر (حتى نفسه) لأنه ليس له قيمة. كما يمكن أن يكون أي قيمة (باستثناء رقم).

لدي شيء وإذا كان لا يساوي رقمًا ، فهل هي سلسلة؟

إجابة قصيرة جدا:

لأن ما يلي: nan / nan = 1 يجب ألا تمسك. غير ذلك inf/inf سيكون 1.

(لذلك nan لا يمكن أن يكون مساويا ل nan. أما بالنسبة لل > أو <, ، لو nan هل احترم أي علاقة ترتيب في مجموعة ترضي خاصية أرخميدية ، سنحصل مرة أخرى nan / nan = 1 في الحد).

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