ما هو الخطأ المنطقي (Logic Error)؟
الخطأ المنطقي (logic error) خلل في منطق البرنامج يجعله يُخرج نتيجة خاطئة دون أن يتعطل أو يعرض أي رسالة خطأ. الكود سليم وكل سطر فيه يُنفَّذ، لكنه لا يفعل ما أراده المبرمج.
آخر تحديث 24 سبتمبر 2026
ثلاث درجات اختبار، هي 80 و90 و100، متوسطها 90. هذا البرنامج يعمل دون أي اعتراض ويطبع شيئًا آخر:
Average: 203.33333333333334
نفّذت بايثون ما يقوله السطر بالضبط. القسمة تسبق الجمع، فلم تُقسم على 3 إلا الدرجة الأخيرة، والنتيجة هي 80 + 90 + 33.33. كان المبرمج يقصد (scores[0] + scores[1] + scores[2]) / 3. أضف الأقواس فيطبع البرنامج Average: 90.0.
لماذا لا تظهر رسالة خطأ
يفحص الحاسوب ما إذا كان الكود سليمًا، لا ما إذا كان صحيحًا. يفحص المحلل النحوي القواعد النحوية، فيلتقط الخطأ في الصياغة. وتفحص بيئة التشغيل كل عملية، فتلتقط خطأ وقت التشغيل مثل القسمة على صفر. جمع ثلاثة أرقام وقسمة أحدها على 3 صياغة سليمة وعملية مشروعة، فيجتاز الفحصين.
وحده من كتب البرنامج يعرف أنه كان يُفترض أن يحسب متوسطًا. هذه النية غير موجودة في أي مكان في الكود، فلا تستطيع أي أداة مقارنة النتيجة بها. الخطأ المنطقي هو الفجوة بين ما طلبته من الحاسوب وما أردته منه.
أشهر أسباب الأخطاء المنطقية
معظم الأخطاء المنطقية تأتي من قائمة قصيرة من الأنماط.
- أخطاء الفرق بواحد (off-by-one). حلقة تتكرر مرة زائدة أو ناقصة.
range(1, 5)تُنتج 1 و2 و3 و4، لأن النهاية مستثناة. راجع صفحة التكرار. - أولوية العمليات.
a + b / 2تقسمbوحدها، كما في المتوسط أعلاه. - المقارنة الخاطئة.
<حيث تلزم<=، أوandحيث تلزمor. الشروط تعبيرات من نوع القيمة المنطقية، وعامل واحد خاطئ يقلب النتيجة مع بعض المدخلات. - الشروط بترتيب خاطئ. في سلسلة
ifوelifيفوز أول شرط صحيح، فالاختبار الواسع الموضوع أولًا يحجب الاختبارات الأضيق التي تحته. - المتغير الخاطئ. تحديث
totalداخل الحلقة ثم طباعةsubtotal. - افتراضات عن الأرقام.
0.1 + 0.2 == 0.3قيمتهاFalseفي بايثون وجافا وجافا سكريبت، لأن الأعداد العشرية (floating point) تقريبية. و7 // 2تساوي 3 لا 3.5.
هذا هو خطأ ترتيب الشروط. الدرجة 95 يجب أن تكون A:
D
D
F
الدرجة 95 أكبر من 60 أو تساويها، فيفوز الفرع الأول ولا يُوصل إلى elif أبدًا. ضع أعلى حدّ أولًا فتصبح كل النتائج صحيحة.
أنواع الأخطاء في البرمجة
تُصنَّف أخطاء البرمجة عادةً في ثلاثة أنواع بحسب وقت ظهورها وما يُبلغ عنها.
| خطأ في الصياغة | خطأ وقت التشغيل | خطأ منطقي | |
|---|---|---|---|
| متى يظهر | قبل تشغيل البرنامج | أثناء التشغيل | أثناء التشغيل، أو لا يُلاحظ أبدًا |
| ما الذي يكتشفه | المحلل النحوي أو المترجم | بيئة التشغيل أو نظام التشغيل | شخص أو اختبار |
| هل يعمل البرنامج؟ | لا | حتى السطر الفاشل | نعم، حتى النهاية |
| رسالة الخطأ | نعم، مع رقم السطر | نعم، مع traceback | لا توجد |
| مثال في بايثون | if x > 3 بلا نقطتين رأسيتين | 10 / 0 | a + b / 2 لحساب متوسط |
| كيف تجده | اقرأ الرسالة | اقرأ الـ traceback | قارن المخرجات بإجابة معروفة |
بعض الكتب تسرد أنواعًا أكثر، ومعظمها يندرج تحت هذه الثلاثة. خطأ النوع الذي يرفضه مترجم جافا، مثل incompatible types: String cannot be converted to int، يُكتشف وقت الترجمة كخطأ الصياغة، وبعض الكتب تسميه خطأً دلاليًا. وخطأ الربط (linker error) يقع في الخطوة الأخيرة من بناء برنامج بلغة C أو C++، عندما تكون دالة مُصرَّحًا عنها لكن كودها غير موجود في أي مكان. وأخطاء الحساب والموارد والملفات، مثل القسمة على صفر أو نفاد الذاكرة أو فتح ملف غير موجود، كلها أخطاء وقت تشغيل. كما تستخدم بعض الدورات مصطلح "الخطأ الدلالي" اسمًا آخر للخطأ المنطقي، فتحقق من المعنى الذي يقصده الكتاب.
كيف تجد الخطأ المنطقي
- اختبر بإجابة تعرفها مسبقًا. احسب النتيجة الصحيحة يدويًا لمدخل صغير، ثم قارن. التحقق من ثلاث درجات أسهل من التحقق من ثلاثة آلاف.
- اطبع القيم الوسيطة. طباعة
scoreوالفرع الذي اتُّخذ، أو عداد الحلقة في كل دورة، تُظهر الخطوة الدقيقة التي يبتعد عندها الواقع عن خطتك. - تتبّع الكود خطوة بخطوة بالمُنقِّح. وضع نقطة توقف وتنفيذ سطر واحد في كل مرة يؤدي الغرض نفسه دون تعديل الكود.
- اختبر الحدود. جرّب 0 و1 وأكبر قيمة وقائمة فارغة والحدّ نفسه بالضبط (60 و90 في مثال الدرجات).
- اشرح الكود بصوت مسموع. وصف كل سطر لشخص آخر، أو لبطة مطاطية، يجبرك على قول ما يفعله السطر فعلًا لا ما تفترض أنه يفعله.
تحوّل assert الإجابة المعروفة إلى فحص تلقائي. لا تفعل شيئًا حين يكون الشرط صحيحًا، وتوقف البرنامج حين يكون خاطئًا:
Traceback (most recent call last):
File "main.py", line 10, in <module>
assert grade(95) == "A", "95 should be an A"
^^^^^^^^^^^^^^^^
AssertionError: 95 should be an A
الاختبار الفاشل يحوّل الخطأ المنطقي الصامت إلى خطأ صاخب مع رقم سطر. وهذه هي الفكرة الكاملة وراء اختبار الوحدات (unit testing).
الأخطاء المنطقية في لغات أخرى
الأنماط واحدة في كل مكان، لكن لكل لغة فخاخها. في جافا سكريبت، "5" + 3 هي النص "53"، بينما "5" - 3 هي الرقم 2، فالقيمة المقروءة من نموذج على شكل نص قد تُجمع جمعًا خاطئًا دون أي خطأ. وفي لغة C، if (x = 5) تُسند 5 إلى x وتكون صحيحة دائمًا. يحذّر Clang منها افتراضيًا (using the result of an assignment as a condition without parentheses)، لكنها تُترجم وتعمل رغم ذلك، فتعامل مع تحذيرات المترجم بجدية الأخطاء نفسها.
إلى أين بعد ذلك
قارن هذه الصفحة بصفحتي الخطأ في الصياغة وخطأ وقت التشغيل لترى كيف يُبلَّغ عن كل نوع. الحلقات هي موطن أخطاء الفرق بواحد، لذا فصفحة التكرار ودليل بايثون عن حلقات for قراءتان مناسبتان بعد ذلك. وللتدرب على اكتشاف النتائج الخاطئة في تمارين حقيقية، جرّب دورة بايثون.
الأسئلة الشائعة
ما الفرق بين خطأ الصياغة والخطأ المنطقي؟
ما هو الخطأ المنطقي في بايثون؟
range(1, 5) حين تريد من 1 إلى 5 شاملة، وa + b / 2 حين تريد (a + b) / 2، وفروع if تُفحص بترتيب خاطئ. لا تستطيع بايثون اكتشافها، لأنها لا تملك وسيلة لمعرفة ما قصدته.