عندما أقوم بحساب كبير مضروب, لماذا أحصل على السلبية ؟

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

  •  04-07-2019
  •  | 
  •  

سؤال

لذا الإجراء بسيط ، حساب مضروب عدد.التعليمات البرمجية كما يلي.

int calcFactorial(int num)
{
    int total = 1;

    if (num == 0)
    {
        return 0;
    }

    for (num; num > 0; num--)
    {
        total *= num;
    }

    return total;
}

الآن, هذا يعمل بشكل جيد وممتاز (هناك بالتأكيد أسرع وأكثر أناقة الحلول ، ولكن هذا يعمل بالنسبة لي) معظم الأرقام.ومع ذلك عند إدخال أعداد أكبر مثل 250 ذلك بصراحة ، الفضلات للخارج.الآن أول زوجين مضروب "بت" عن 250{ 250, 62250, 15126750, 15438000, 3813186000 } لتكون مرجعا.

قانون بلدي يبصق { 250, 62250, 15126750, 15438000, -481781296 } التي من الواضح قبالة.أول شبهة ربما أنني قد خالفت الحد من 32 بت عدد صحيح ، ولكن نظرا لأن 2^32 هي 4294967296 أنا لا أعتقد ذلك.الشيء الوحيد الذي يمكنني التفكير به هو ربما أنه خروقات أ توقيع 32 بت الحد ، ولكن لا ينبغي أن يكون قادرا على التفكير في هذا النوع من الأشياء ؟ لو أن وقعت المشكلة لا يمكن أن تحل هذه بجعل عدد صحيح غير موقعة ولكن هذا لن يكون إلا حلا مؤقتا ، التكرار التالي ينتج 938043756000 وهو أعلى بكثير من 4294967296 الحد.

لذا مشكلتي وقعت الحد ؟ إذا كان الأمر كذلك ، ماذا يمكنني أن أفعل لحساب أعداد كبيرة (على الرغم من أن لدي "LargeInteger" الطبقة صنعت منذ فترة قد تكون مناسبة!) دون أن تصادف هذه المشكلة مرة أخرى ؟

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

المحلول

2^32 لا تعطيك حد توقيع الاعداد الصحيحه.

وقعت صحيح حد فعلا 2147483647 (إذا كنت النامية على ويندوز باستخدام MS أدوات أخرى toolsuites/منصات سيكون لها حدودها الخاصة التي ربما تتشابه).

سوف تحتاج C++ عدد كبير المكتبة مثل هذا واحد.

نصائح أخرى

بالإضافة إلى تعليقات أخرى, أود أن أشير إلى اثنين من خطورة الخلل في التعليمات البرمجية الخاصة بك.

  • لا يوجد لديك الحرس ضد الأرقام السالبة.
  • مضروب الصفر هو واحد وليس صفر.

نعم, لقد ضرب الحد.الباحث في C++, بحكم التعريف, وقعت.و, لا, C++ لا أعتقد أبدا.إذا كنت أقول أن تفعل شيئا, أنها سوف تفعل ذلك حتى لو كان الخطأ الواضح.

النظر في استخدام عدد كبير المكتبة.هناك العديد من حولهم C++.

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

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

بلدي آلة حاسبة ويندوز (ابدأ-تشغيل-احسب) يقول لي ان

hex (3813186000) =         E34899D0
hex (-481781296) = FFFFFFFFE34899D0

لذا نعم, السبب هو توقيع الحد.منذ factorials يمكن من خلال التعريف يكون إلا إيجابيا ، ولا يمكن احتساب أرقام إيجابية ، سواء الحجة و قيمة الإرجاع يجب أن تكون موقعة الأرقام على أي حال.(وأنا أعلم أن الجميع يستخدم int i = 0 في الحلقات ، حتى أناولكن أن تترك جانبا ، يجب أن تستخدم دائما غير موقعة المتغيرات إذا كانت قيمة لا يمكن أن تكون سلبية ، انها ممارسة جيدة المنظمة البحرية الدولية).

المشكلة العامة مع factorials هو أنها يمكن أن تولد بسهولة جدا أعداد كبيرة.هل يمكن استخدام تعويم ، وبالتالي التضحية الدقة ولكن تجنب تجاوز عدد صحيح المشكلة.

يا الانتظار, حسب ما كتبته أعلاه, يجب عليك ان تجعل هذا غير موقعة تعويم ;-)

كنت قد تجاوز المشكلة.Factorials أن تتجاوز حدود الاعداد الصحيحه.يمكنك تغيير وظيفة الخاص بك إلى العودة الزوجي ، لكن ذلك فقط يمكنك شراء مساحة أكبر قليلا.في التطبيقات التي غالبا ما تحتاج إلى مضاعفة factorials مرات في عدد قليل جدا من حيث النتيجة النهائية سوف تناسب داخل مزدوجة ولكن الخطوات الوسيطة لا.هنا مقال يشرح كيفية التعامل مع هذا الوضع: http://www.johndcook.com/blog/2008/04/24/how-to-calculate-binomial-probabilities/

إذا كنت أتذكر جيدا:

غير موقع short int = ماكس 65535

unsigned int = ماكس 4294967295

موقعة طويلة = ماكس 4294967295

غير طويل (Int64 )= max 18446744073709551615

تحرير المصدر:

الباحث/طويلة Max القيم

الحديث المترجم متغير

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