اذهب إلى المحتوى

حسابيّات الأعداد العشرية في ++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

اقرأ أيضًا


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

أفضل التعليقات

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



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...