لماذا يستخدم .NET تقريب المصرفي كإعداد افتراضي؟

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

  •  10-07-2019
  •  | 
  •  

سؤال

وبحسب الوثائق فإن decimal.Round تستخدم الطريقة خوارزمية مستديرة إلى متساوية وهي غير شائعة في معظم التطبيقات.لذلك ينتهي بي الأمر دائمًا بكتابة وظيفة مخصصة للقيام بخوارزمية نصف دائرية أكثر طبيعية:

public static decimal RoundHalfUp(this decimal d, int decimals)
{
    if (decimals < 0)
    {
        throw new ArgumentException("The decimals must be non-negative", 
            "decimals");
    }

    decimal multiplier = (decimal)Math.Pow(10, decimals);
    decimal number = d * multiplier;

    if (decimal.Truncate(number) < number)
    {
        number += 0.5m;
    }
    return decimal.Round(number) / multiplier;
}

هل يعرف أحد السبب وراء قرار تصميم الإطار هذا؟

هل هناك أي تطبيق مدمج لخوارزمية التقريب والنصف في الإطار؟أو ربما بعض واجهات برمجة تطبيقات Windows غير المُدارة؟

يمكن أن يكون مضللاً للمبتدئين الذين يكتبون ببساطة decimal.Round(2.5m, 0) توقع 3 نتيجة لذلك ولكنك تحصل على 2 بدلاً من ذلك.

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

المحلول

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

نصائح أخرى

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

ولكن السؤال لماذا تم الصافي استخدام التقريب الفعلي بانكر كما الافتراضي - والجواب هو أن مايكروسوفت قد اتبعت يختلط <لأ href = "http://en.wikipedia.org/wiki/IEEE_754-2008#Roundings_to_nearest" = "noreferrer"> IEEE 754 المعيار. وهذا مذكور أيضا في MSDN لMath.Round تحت التصريحات.

ونلاحظ أيضا أن صافي يدعم طريقة بديلة المحدد من قبل IEEE خلال توفير التعداد MidpointRounding. ويمكن بالطبع قدمت المزيد من البدائل للحل العلاقات، لكنها تختار فقط استيفاء معيار IEEE.

على الرغم من أنني لا أستطيع الإجابة على سؤال "لماذا اختار مصممو Microsoft هذه الوظيفة كافتراضي؟"، إلا أنني أريد فقط أن أشير إلى أن الوظيفة الإضافية غير ضرورية.

Math.Round يسمح لك بتحديد أ MidpointRounding:

  • ToEven - عندما يكون الرقم في المنتصف بين رقمين آخرين، يتم تقريبه نحو أقرب رقم زوجي.
  • AwayFromZero - عندما يكون الرقم في المنتصف بين رقمين آخرين، يتم تقريبه نحو أقرب رقم بعيد عن الصفر.

تستخدم الكسور العشرية في الغالب مال;يعد تقريب المصرفي أمرًا شائعًا عند العمل معه مال.أو يمكنك القول.

معظمهم من المصرفيين الذين يحتاجون إلى نوع عشري.لذلك فهي "تقريب المصرفي"

يتمتع التقريب المصرفي بميزة أنك ستحصل في المتوسط ​​على نفس النتيجة إذا:

  • قم بتدوير مجموعة من "بنود الفاتورة" قبل إضافتها،
  • أو قم بإضافتها ثم تقريب المجموع

لقد أدى التقريب قبل الجمع إلى توفير الكثير من العمل في الأيام التي سبقت ظهور أجهزة الكمبيوتر.

(في المملكة المتحدة، عندما اتبعنا النظام العشري، لم تكن البنوك تتعامل بنصف بنس، ولكن لسنوات عديدة كان لا يزال هناك عملة معدنية بقيمة نصف بنس، وغالبًا ما كانت أسعار المتاجر تنتهي بنصف بنس - لذلك كان هناك الكثير من التقريب)

استخدم تحميلًا زائدًا آخر لوظيفة Round مثل هذا:

decimal.Round(2.5m, 0,MidpointRounding.AwayFromZero)

سوف يخرج 3.وإذا كنت تستخدم

decimal.Round(2.5m, 0,MidpointRounding.ToEven)

سوف تحصل على تقريب المصرفي.

لاحظ أيضا أن "التقريب" عبر سلسلة تنسيق (مثل "0") تنتج نتيجة مختلفة من "Math.Round ()". أي أن 5، 0.5، الخ .. ودائما جمعوا:

let d, d' = 2.5, 3.5

Debug.WriteLine(Math.Round(d))      // 2.5 -> 2
Debug.WriteLine(d.ToString("0"))    // 2.5 -> 3

Debug.WriteLine(Math.Round(d'))     // 3.5 -> 4
Debug.WriteLine(d'.ToString("0"))   // 3.5 -> 4


let dd, dd' = 2.25, 2.35

Debug.WriteLine(Math.Round(dd, 1))     // 2.25 -> 2.2
Debug.WriteLine(dd.ToString("0.0"))    // 2.25 -> 2.3

Debug.WriteLine(Math.Round(dd', 1))    // 2.35 -> 2.4
Debug.WriteLine(dd'.ToString("0.0"))   // 2.35 -> 2.4
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top