المستوى: مبتدئ
لو كتبت 0.1 + 0.2 في الكود وطلعلك 0.30000000000000004، يبقى المقال ده ليك. هتفهم ليه ده بيحصل في كل لغات البرمجة (مش JavaScript بس)، وامتى لازم تتدخّل، وامتى عادي تتجاهل.
ليه 0.1 + 0.2 مش بيساوي 0.3 في الكمبيوتر
المشكلة باختصار
افتح Console في المتصفح واكتب الأمر ده:
console.log(0.1 + 0.2);
// النتيجة: 0.30000000000000004اعمل نفس الحاجة في Python:
print(0.1 + 0.2)
# النتيجة: 0.30000000000000004في Java و C++ و Go و Ruby و Swift و PHP و C#، النتيجة هي هي. ده مش bug في اللغة ولا في المعالج بتاعك. ده سلوك معتمد ومتفق عليه في كل المعالجات الحديثة من سنة 1985.
المثال البسيط — قسمة الكيكة على 3
تخيل إن عندك كيكة عايز تقسمها بالتساوي على 3 ناس. الجواب الحقيقي 0.333333... وعلامة "..." معناها أرقام بتفضل تتكرر للأبد. لكن لو معاك ورقة فيها 8 خانات بس بعد العلامة العشرية، هتكتب 0.33333333 وتقف. الرقم اللي كتبته أقل من الثلث الحقيقي بمقدار صغير جدًا. لو ضربت في 3 الإجابة هتطلع 0.99999999 مش 1 صحيحة.
الكمبيوتر بيعمل نفس الحاجة بالظبط، لكن بالنظام الثنائي (binary) مش العشري. الفرق المهم إن الكمبيوتر مش عنده مشكلة مع 0.5 أو 0.25 أو 0.75 لأنها كسور من قوى 2. المشكلة بتظهر مع 0.1 و 0.2 و 0.3، لأنها كسور دورية لا نهائية في binary.
التعريف العلمي — معيار IEEE 754
الكمبيوتر بيخزّن الأرقام العشرية بصيغة اسمها IEEE 754 double precision في 64 bit مقسومين كالآتي:
- 1 bit للإشارة (موجب أو سالب)
- 11 bit للأس (exponent)
- 52 bit للجزء الكسري (mantissa)
الرقم 0.1 في binary هو 0.0001100110011001100... وهكذا للأبد. التمثيل بـ 52 bit بيقطع التتابع، فيتخزّن كرقم أقرب وهو فعلياً 0.1000000000000000055511151231257827021181583404541015625. ده اللي بيخلّي 0.1 + 0.2 = 0.30000000000000004 بدل 0.3 المفترض.