يفترض كثير من المبرمجين خطأً أن الشيفرة التالية ستعمل كما هو مخطط لها:
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
كنتيجة، وهي الإجابة الصحيحة. لكن لا يحدث ذلك لسببين:
-
لن ينتهي البرنامج أبدًا بهيئته الحالية، لأنّ
a
لن تساوي أبدًا القيمة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
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.