المستوى: مبتدئ — لو عمرك كتبت كود بيجمع أو يضرب أرقام، المقال ده ليك، حتى لو لسه في أول الطريق.
Integer Overflow: ليه 2147483647 + 1 بيديك رقم سالب؟
لو كتبت 2147483647 + 1 في C أو Java وطلع لك -2147483648، ده مش عطل في جهازك. ده سلوك اسمه Integer Overflow. هنا هتفهم ليه بيحصل بمثال بسيط، تجرّبه بنفسك بكود، وتعرف إمتى لازم تاخد بالك منه قبل ما يوقّع نظامك.
الفكرة الأول بمثال: عدّاد كيلومترات العربية
تخيّل عدّاد كيلومترات قديم، ميكانيكي، بخمس خانات. أقصى رقم يقدر يوصله هو 99999. لو مشيت كيلومتر واحد زيادة، الخانات كلها بتلفّ وترجع 00000، مش 100000. الخانة السادسة مش موجودة أصلًا، فمفيش مكان يتخزّن فيه الرقم.
الأعداد في الكمبيوتر بتشتغل بنفس المنطق بالظبط. كل نوع رقم له عدد خانات ثابت. لما توصل لأقصى قيمة وتزوّد واحد، الرقم بيلفّ. الفرق الوحيد إن الكمبيوتر بيحسب بالنظام الثنائي، وأول خانة بتحدّد الإشارة، فاللفّة بترجّعك لأصغر رقم سالب بدل الصفر.
الشرح العلمي: بِتات ثابتة وبِت للإشارة
النوع int في لغات زي C وJava وGo بياخد 32 بِت في الذاكرة، يعني 4 بايت. من الـ 32 بِت دول، واحد محجوز لإشارة الرقم، والباقي للقيمة. النتيجة إن أكبر رقم موجب تقدر تخزّنه هو 2147483647، وأصغر رقم سالب هو -2147483648.
التمثيل ده اسمه المتمم الثنائي (Two's Complement). لما تبقى كل بِتات القيمة مليانة واحدات وتزوّد 1، الجمع بيقلب بِت الإشارة من 0 لـ 1، فالرقم فجأة بيتفسّر على إنه أصغر رقم سالب. مفيش رسالة خطأ، الحساب بيكمّل بهدوء بقيمة غلط. ده أخطر جزء في الموضوع.
جرّبها بنفسك
في C السلوك ده واضح ومباشر:
#include <stdio.h>
int main(void) {
int x = 2147483647;
printf("%d\n", x + 1);
return 0;
}
في بايثون الموضوع مختلف. أعداد بايثون الصحيحة مرنة الحجم، فبتكبر تلقائيًا ومفيش overflow. عشان تشوف السلوك الحقيقي للأنواع الثابتة، استخدم numpy:
import numpy as np
x = np.int32(2147483647)
print(x + np.int32(1))
print(2147483647 + 1)
جرّب الكود ده بنفسك. لو شفت الرقم السالب في نسخة الـ int32 والرقم الكبير في بايثون العادية، يبقى فهمت الـ overflow بعينك.