سؤال

لدي طريقة تتعامل مع بعض الإحداثيات الجغرافية في .NET ، ولدي بنية تخزن زوجًا من الإحداثيات ، بحيث إذا تم تمرير 256 في أحد الإحداثيات ، فإنه يصبح 0. ومع ذلك ، في حالة معينة ، قيمة يتم حساب ما يقرب من 255.99999998 ، وبالتالي تخزين في البنية. عندما يتم طباعته في ToString () ، يصبح 256 ، وهو ما يجب أن يحدث - 256 يجب أن يكون 0. لا أمانع إذا طبعت 255.9999998 ولكن حقيقة أنه يطبع 256 عندما يعرض مصحح الأخطاء 255.9999998 مشكلة. سيكون الحصول على كل من المتجر والعرض 0 أفضل.

على وجه التحديد هناك مشكلة مع المقارنة. 255.99999998 هو قريب بما فيه الكفاية من 256 بحيث ينبغي أن يساويها. ماذا علي أن أفعل عند مقارنة الزوجي؟ استخدام نوع من قيمة epsilon؟


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

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

المحلول

يمكنك استخدام نهج Epsilon ، لكن Epsilon عادة ما يكون حلوى للتغلب على حقيقة أن الحساب النقطة العائمة هو فقدان.

قد تفكر في تجنب النقاط العائمة الثنائية تمامًا واستخدام فئة عقلانية لطيفة.

ربما كان من المقرر أن يكون الحساب أعلاه 256 إذا كنت تقوم بحسابية خاسرة كما ستحصل على نوع عقلاني.

يمكن أن تسير الأنواع العقلانية باسم النسبة أو فئة الكسر ، وهي بسيطة إلى حد ما في الكتابة

هنا واحد مثال. هنا اخر


يحرر....

لفهم مشكلتك ، ضع في اعتبارك أنه عندما يتم تحويل القيمة العشرية 0.01 إلى تمثيل ثنائي ، لا يمكن تخزينها بالضبط في الذاكرة المحدودة. تمثيل hexidecimal لهذه القيمة هو 0.028F5C28F5C حيث يتكرر "28F5C" بلا حدود. لذلك حتى قبل إجراء أي حسابات ، فإنك تفقد الدقة فقط عن طريق تخزين 0.01 بتنسيق ثنائي.

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

لغرضك ما زلت أقترح نوعًا عقلانيًا.

نصائح أخرى

هذا يبدو وكأنه مشكلة في كيفية طباعة الرقم ، وليس كيف يتم تخزينه. أ double لديه حوالي 15 شخصية مهمة ، لذلك يمكن أن تخبر 255.99999998 من 256 بدقة لتجنيب.

يمكنك اختيار سلاسل التنسيق التي يجب أن تتيح لك عرض أكبر عدد من الرقم كما تريد.

تتمثل الطريقة المعتادة لمقارنة الزوجي من أجل المساواة في طرحها ومعرفة ما إذا كانت القيمة المطلقة أقل من بعض Epsilon المحددة مسبقًا ، وربما 0.000001.

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

أود أن أذهب مع نوع غير موقّع مع الحجم المعروف (على سبيل المثال. UINT32 أو UINT64 إذا كانت متوفرة ، لا أعرف .NET) وأعامله كنوع رقم نقطة ثابت MOD 256.

على سبيل المثال.

typedef uint32 fixed;

inline fixed to_fixed(double d)
{
    return (fixed)(fmod(d, 256.) * (double)(1 << 24))
}

inline double to_double(fixed f)
{
    return (double)f / (double)(1 << 24);
}

أو شيء أكثر توضيحًا لتناسب اتفاقية التقريب (إلى الأقرب ، إلى الأسفل ، إلى أعلى ، إلى غريب ، حتى). أعلى 8 بت من الثابتة تمسك الجزء الأيمن ، فإن البتات السفلية الـ 24 تحمل الجزء الكسري. الدقة المطلقة هي 2^{-24}.

لاحظ أن إضافة مثل هذه الأرقام وفروعها تتفوق بشكل طبيعي في 256. للضرب ، يجب أن تحذو.

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