التقريب إلى الكل في .NET

كل كو الملتحي ، الرفاق!

نعلم جميعا ما هو التقريب. إذا نسي شخص ما ، فسيكون التقريب هو استبدال الرقم بقيمة تقريبية ، مكتوبًا بأرقام أقل أهمية. إذا سألت أي شخص على الطاير عما يحدث عندما تقوم بالدوران 6.5 إلى الأعداد الصحيحة ، فسوف يجيب على "7" دون تردد. لقد تعلمنا من المدرسة أن الأرقام يتم تقريبها إلى أقرب عدد صحيح ، وهو أكبر من حيث القيمة المطلقة. أي إذا كان العدد الكسري في العدد المستدير يساوي أو يزيد عن نصف التفريغ للجزء بالكامل ، فإننا نجمع الرقم الأصلي إلى أقرب رقم أكبر.

ببساطة:
6,4 = 6 6,5 = 7 6,6 = 7 
إلخ

وهكذا ، مع ترك المدرسة وتصبح مبرمجًا ، نتوقع غالبًا نفس السلوك من لغات البرمجة القوية لدينا. ننسى تمامًا أننا في المدرسة تعلمنا "التقريب الرياضي" ، ولكن في الواقع هناك أنواع أكثر بكثير من التقريب. في ويكيبيديا وحدها ، يمكنك حفر عدد خيارات التقريب 0.5 إلى أقرب عدد صحيح:

  • التقريب الرياضي
  • التقريب عشوائي
  • بالتناوب التقريب
  • تقريب البنك

النوع الأول ، "التقريب الرياضي" ، تعلمنا جميعًا من المدرسة. يمكنك أن تقرأ عن النوعين الثاني والثالث في وقت فراغك ، فهي ليست مثيرة للاهتمام بالنسبة لي في هذا المقال اليوم.

لكن "التقريب المصرفي" مثير للاهتمام بالفعل. "لماذا؟" - أنت تسأل. في الشبكة الفرعية ، غالبًا ما نستخدم فئة تحويل ، والتي توفر الكثير من الطرق لتحويل نوع بيانات واحد إلى آخر (يجب عدم الخلط بينه وبين طاقم العمل ، سيتم وصفه أدناه). والآن ، اتضح أنه عند تحويل أرقام الفاصلة العائمة ( مزدوجة ، عائمة ، عشرية ) إلى نوع صحيح صحيح من خلال أسلوب Convert.ToInt32 ، يعمل التقريب "المصرفي" تحت الغطاء. يتم استخدامه هنا افتراضيا!

ويبدو أن جهل هذا تافه لا يؤثر بشكل كبير على عملك ، ولكن بمجرد أن تضطر إلى العمل مع الإحصاءات وحساب المؤشرات على أساس مجموعة من جميع أنواع السجلات والأرقام ، سيظهر هذا الشيء في اتجاه جانبي. لأننا نتوقع (من الجهل) أن تعمل جميع التحويلات / التقريب في الحسابات وفقًا لقواعد التقريب "الرياضي". ونبدو مثل كبش على بوابة جديدة نتيجة التقريب 6.5 ، وهو 6 .

الفكرة الأولى للمبرمج الذي يرى ذلك هي: "ربما يكون التقريب يعمل في الاتجاه المعاكس ، ووفقًا للقواعد التي يتم تقريبها إلى أقل عدد؟" ، "ربما نسيت شيئًا من الرياضيات المدرسية؟". ثم يذهب إلى google ويفهم أنهم لم ينسوا شيئًا ما ، وأن هناك نوعًا من الغوغاء يجري. في هذه الخطوة ، سيقرر المطور البطيء أن هذا هو السلوك القياسي لأسلوب Convert.ToInt32 ، ثم التقريب إلى أصغر عدد صحيح ، والنتيجة لمزيد من البحث. وسوف يعتقد أنه إذا Convert.ToInt32 (6،5) = 6 ، ثم عن طريق القياس Convert.ToInt32 (7،5) = 7 . ولكن كان هناك. في المستقبل ، سيتم ضرب هؤلاء المطورين على رأسهم مع مجموعة من الأخطاء من قسم ضمان الجودة.

والحقيقة هي أن التقريب "المصرفي" يعمل بشكل أصعب بعض الشيء - فهو يقرب رقمًا إلى أقرب عدد صحيح ، وليس إلى أقرب عدد صحيح. من المفترض أن هذا النوع من التقريب أكثر صدقًا في حالة التطبيق في العمليات المصرفية - لن تحرم البنوك نفسها أو العملاء ، على افتراض أن هناك عددًا كبيرًا من العمليات مع جزء صحيح أكبر مثل العمليات التي بها جزء صحيح فردي. ولكن بالنسبة لي - لا يزال غير واضح :) ولهذا السبب ستعطي Convert.ToInt32 (6.5) نتيجة 6 ، وستكون نتيجة Convert.ToInt32 (7.5) 8 ، وليس 7 :)

ما يجب القيام به للحصول على التقريب "الرياضي" للجميع؟ لا تحتوي أساليب تحويل الفئة على خيارات تقريب إضافية. هذا صحيح ، لأن هذا الفصل لا يخدم في المقام الأول في التقريب ، ولكن لتحويل النوع. تأتي فئة الرياضيات الرائعة بأسلوبها الدائري في عملية الإنقاذ. لكن عليك أيضًا توخي الحذر ، لأن هذا الأسلوب يعمل افتراضيًا مثل التقريب في Convert.ToInt32 () - وفقًا للقاعدة "المصرفية". ومع ذلك ، يمكن تغيير هذا السلوك باستخدام الوسيطة الثانية ، والتي تعد جزءًا من أسلوب Round . لذلك ، Math.Round (someNumber ، MidpointRounding.ToEven ) سيعطينا التقريب الافتراضي "المصرفي". لكن Math.Round (someNumber ، MidpointRounding.AwayFromZero ) ستعمل وفقًا للقواعد المعتادة للتقريب "الرياضي".

وبالمناسبة ، لا يستخدم Convert.ToInt32 () System.Math.Round () تحت الغطاء. حفر الحفر بشكل خاص لتنفيذ هذه الطريقة على جيثب - التقريب يعتبر وفقا للالمتبقيات:

 public static int ToInt32(double value) { if (value >= 0) { if (value < 2147483647.5) { int result = (int)value; double dif = value - result; if (dif > 0.5 || dif == 0.5 && (result & 1) != 0) result++; return result; } } else { if (value >= -2147483648.5) { int result = (int)value; double dif = value - result; if (dif < -0.5 || dif == -0.5 && (result & 1) != 0) result--; return result; } } throw new OverflowException(Environment.GetResourceString("Overflow_Int32")); } 

وأخيرًا ، بضع كلمات حول نوع الكتابة :

 var number = 6.9; var intNumber = (int)number; 

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

روابط ذات صلة:


ملاحظة: بفضل مكسيم Yakushkin لجذب الانتباه إلى هذه اللحظة الضمنية.

PPS بالمناسبة ، في بيثون ، التقريب الافتراضي يعمل بنفس الطريقة على أساس "مصرفي". ربما نفس الشيء في لغتك ، كن حذرا مع الأرقام :)

Source: https://habr.com/ru/post/ar462299/


All Articles