سلسلة ++c للمحترفين الدرس 4: حسابيّات الأعداد العشرية في ++C


محمد الميداوي

يفترض كثير من المبرمجين خطأً أن الشيفرة التالية ستعمل كما هو مخطط لها:

float total = 0;
for (float a = 0; a != 2; a += 0.01f) {
    total += a;
}

إذ يفترض المبرمج المبتدئ أن تلك الشيفرة ستجمع كل الأعداد الموجودة في النطاق المحصور بين 0، 0.01، 0.02، 0.03، … ، 1.97، 1.98، 1.99، للحصول في النهاية على 199 كنتيجة، وهي الإجابة الصحيحة. لكن لا يحدث ذلك لسببين:

  1. لن ينتهي البرنامج أبدًا بهيئته الحالية، لأنّ a لن تساوي أبدًا القيمة 2، والحلقة التكرارية لن تنتهي.
  2. إذا عدّلنا شرط الحلقة التكرارية وجعلناه a < 2، فإنّ الحلقة التكرارية ستنتهي، لكن الإجمالي سيكون شيئًا غير 199 التي نريدها، وعلى الأغلب ستحصل على 201 على الأجهزة المتوافقة مع معيار IEEE754.

سبب حدوث ذلك هو أنّ الأعداد العشرية (Floating Point Numbers) تمثِّل القيم بشكل تقريبي وحسب. كما في المثال التالي:

    double a = 0.1;
    double b = 0.2;
    double c = 0.3;

    if (a + b == c)
        // IEEE754 لن يُطبع هذا على الأجهزة المتوافقة مع 
        std::cout << "This Computer is Magic!" << std::endl;
    else
        std::cout << "This Computer is pretty normal, all things considered." << std::endl;

برغم أننا كمبرمجين نرى ثلاثة أعداد مكتوبة وفق النظام العشري، إلا أن المصرِّف (Compiler) -والحاسوب الذي يعمل عليه- لا يرى إلا أرقامًا ثنائية، لذا يجب أن تخزَّن تلك الأعداد في صيغ تقريبية غير دقيقة كما في حالة العدد 1/3 إذ يخزن على الصورة 0.3333333333 في النظام العشري، وذلك لأن 0.1 و 0.2 و 0.3 تتطلب قسمة تامة على 10، وهذا يسير في النظام العشري لكنه مستحيل في النظام الثنائي.

    // الأعداد العشرية في نظام 64-بت لديها 53 خانة رقمية، بما في ذلك الجزء الصحيح من العدد
    double a = 0011111110111001100110011001100110011001100110011001100110011010;

    // تمثيل تقريبي للعدد 0.1
    double b = 0011111111001001100110011001100110011001100110011001100110011010;

    // تمثيل تقريبي للعدد 0.2
    double c = 0011111111010011001100110011001100110011001100110011001100110011;

    // تمثيل تقريبي للعدد 0.3
    double a + b = 0011111111010011001100110011001100110011001100110011001100110100;
    // 0.3 لاحظ أن هذا العدد لا يساوي

هذا الدرس جزء من سلسلة دروس عن C++‎.

ترجمة -وبتصرّف- للفصل Chapter 4: Floating Point Arithmetic من كتاب C++ Notes for Professionals

اقرأ أيضًا





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن