مشكلة وحل 25: حل خطأ ZeroDivisionError: division by zero في بايثون

حل خطأ ZeroDivisionError division by zero في بايثون

في هذا المقال من سلسلة مشكلة وحل سنتعلم طريقة حل خطأ ZeroDivisionError: division by zero في بايثون، وهو من الأخطاء الشائعة التي تظهر عندما يحاول البرنامج قسمة رقم على صفر.

قد يظهر لك الخطأ أثناء كتابة كود بسيط للقسمة، أو عند استقبال رقم من المستخدم، أو عند حساب النسبة المئوية، أو حتى عند حساب متوسط قائمة فارغة. المهم أن تفهم السبب قبل نسخ الحل، لأن نفس الخطأ قد يظهر بأكثر من رسالة مثل float division by zero أو integer division or modulo by zero.

{alertInfo} الفكرة المختصرة: الخطأ يظهر عندما يكون المقسوم عليه صفرًا. الحل الأفضل غالبًا هو فحص القيمة قبل القسمة، أو استخدام try و except عندما تكون القيمة قادمة من المستخدم أو من مصدر غير مضمون.

{getToc} $title={محتوى المقال}

ما معنى خطأ ZeroDivisionError: division by zero؟

معنى خطأ ZeroDivisionError: division by zero أن بايثون حاولت تنفيذ عملية قسمة، لكن الرقم الموجود بعد علامة القسمة كان صفرًا.

مثال بسيط يسبب الخطأ:

result = 10 / 0

print(result)

عند تشغيل الكود سيظهر خطأ يشبه:

ZeroDivisionError: division by zero

السبب أن القسمة على صفر غير مسموحة، لذلك يوقف بايثون تنفيذ البرنامج ويعرض رسالة الخطأ بدل أن يعطي نتيجة غير صحيحة.

سبب ظهور خطأ القسمة على صفر في بايثون

متى يظهر هذا الخطأ في بايثون؟

يظهر خطأ ZeroDivisionError عند استخدام صفر في الجهة اليمنى من عمليات القسمة أو باقي القسمة. لا يظهر فقط مع الرمز /، بل قد يظهر أيضًا مع // و %.

العملية مثال يسبب الخطأ رسالة شائعة
القسمة العادية 10 / 0 division by zero
القسمة الصحيحة 10 // 0 integer division or modulo by zero
باقي القسمة 10 % 0 integer modulo by zero
القسمة العشرية 10.0 / 0.0 float division by zero

إذن إذا وجدت رسالة float division by zero أو integer division or modulo by zero فهي غالبًا نفس المشكلة: توجد عملية حسابية يستخدم فيها البرنامج صفرًا كمقسوم عليه.

كيف تقرأ رسالة الخطأ؟

عندما يظهر الخطأ، لا تنظر إلى آخر سطر فقط. اقرأ السطر الذي يشير إليه Traceback، لأنه يوضح أين حدثت القسمة على صفر.

مثال:

price = 100
quantity = 0

average_price = price / quantity

print(average_price)

المشكلة هنا ليست في اسم المتغيرات، بل في أن quantity قيمته صفر. لذلك اسأل نفسك دائمًا: ما المتغير الموجود بعد علامة القسمة؟ وهل يمكن أن تكون قيمته صفرًا؟

{alertWarning} لا تبحث عن الحل في السطر الأخير فقط. ابحث عن العملية الحسابية التي تستخدم / أو // أو %، ثم افحص قيمة المتغير الموجود بعد العملية.

الحل الأول: افحص المقسوم عليه قبل القسمة

أفضل حل عندما تكون قادرًا على التحكم في القيم هو فحص المقسوم عليه قبل تنفيذ القسمة.

number = 10
divider = 0

if divider != 0:
    result = number / divider
    print("النتيجة:", result)
else:
    print("لا يمكن القسمة على صفر")

هذا الحل واضح جدًا للمبتدئين؛ لأن البرنامج لا يدخل إلى عملية القسمة أصلًا إلا إذا كانت قيمة divider مختلفة عن صفر.

الحل الثاني: استخدم دالة آمنة للقسمة

إذا كانت القسمة تتكرر في أكثر من مكان داخل مشروعك، فمن الأفضل أن تكتب دالة صغيرة تتولى الفحص بدل تكرار الشرط في كل مرة.

def safe_divide(number, divider):
    if divider == 0:
        return None

    return number / divider


result = safe_divide(10, 0)

if result is None:
    print("لا يمكن القسمة على صفر")
else:
    print("النتيجة:", result)

استخدام None هنا أفضل من إرجاع صفر مباشرة في كل الحالات، لأن الصفر قد يكون نتيجة حقيقية أحيانًا. أما None فيوضح أن العملية لم تتم.

{alertInfo} لا تجعل 10 / 0 تساوي صفرًا تلقائيًا في كل البرامج. أحيانًا هذا يخفي مشكلة منطقية في البيانات، خصوصًا عند حساب النسب والمتوسطات.

الحل الثالث: استخدم try و except مع إدخال المستخدم

عندما تكون القيم قادمة من المستخدم، قد يدخل المستخدم صفرًا أو نصًا بدل رقم. في هذه الحالة يمكن استخدام try و except للتعامل مع أكثر من خطأ بطريقة منظمة.

التعامل مع إدخال المستخدم عند القسمة على صفر في بايثون
try:
    num1 = float(input("أدخل الرقم الأول: "))
    num2 = float(input("أدخل الرقم الثاني: "))

    result = num1 / num2

    print("النتيجة:", result)

except ValueError:
    print("يجب إدخال أرقام فقط")

except ZeroDivisionError:
    print("لا يمكن القسمة على صفر")

هذا المثال يعالج حالتين شائعتين:

  • إذا أدخل المستخدم نصًا بدل رقم، يظهر ValueError.
  • إذا أدخل المستخدم صفرًا في الرقم الثاني، يظهر ZeroDivisionError.
استخدام try except لحل خطأ ZeroDivisionError في بايثون

متى أستخدم الشرط ومتى أستخدم try except؟

كلا الحلين صحيح، لكن اختيار الطريقة يعتمد على حالتك.

الحالة الحل الأفضل غالبًا
القيمة واضحة داخل الكود ويمكن فحصها بسهولة استخدم شرط if divider != 0
القيمة قادمة من مستخدم أو ملف أو مصدر خارجي استخدم try و except مع التحقق المناسب
القسمة تتكرر في أكثر من مكان اكتب دالة مثل safe_divide
تريد منع الخطأ قبل حدوثه استخدم شرطًا قبل القسمة
تريد أن يستمر البرنامج حتى لو حدث الخطأ استخدم try except

مثال شائع: خطأ القسمة على صفر عند حساب المتوسط

من الحالات التي تربك المبتدئين أن يظهر الخطأ عند حساب متوسط قائمة. قد تكون القائمة فارغة، وبالتالي يكون عدد العناصر صفرًا.

خطأ القسمة على صفر عند حساب متوسط قائمة فارغة في بايثون

مثال يسبب الخطأ:

scores = []

average = sum(scores) / len(scores)

print(average)

هنا len(scores) تساوي صفرًا، لذلك تصبح العملية مثل:

0 / 0

الحل:

scores = []

if len(scores) > 0:
    average = sum(scores) / len(scores)
    print("المتوسط:", average)
else:
    print("لا يمكن حساب المتوسط لأن القائمة فارغة")

ويمكنك كتابة الشرط بطريقة أقصر:

if scores:
    average = sum(scores) / len(scores)
    print("المتوسط:", average)
else:
    print("القائمة فارغة")

مثال عملي: برنامج قسمة آمن للمبتدئين

هذا مثال كامل يجمع بين إدخال المستخدم، التحقق من الأرقام، والتعامل مع خطأ القسمة على صفر.

def divide_numbers():
    try:
        first_number = float(input("أدخل الرقم الأول: "))
        second_number = float(input("أدخل الرقم الثاني: "))

        if second_number == 0:
            print("لا يمكن القسمة على صفر")
            return

        result = first_number / second_number
        print("النتيجة:", result)

    except ValueError:
        print("الرجاء إدخال أرقام صحيحة")


divide_numbers()

في هذا المثال استخدمنا الشرط لمنع القسمة على صفر قبل حدوثها، واستخدمنا except ValueError للتعامل مع الإدخال غير الرقمي.

هل من الصحيح استخدام except Exception؟

قد تجد بعض الأمثلة تستخدم except Exception لالتقاط كل الأخطاء، لكن هذا ليس أفضل حل للمبتدئ في هذه الحالة. الأفضل أن تحدد الخطأ الذي تتوقعه.

مثال غير مفضل:

try:
    result = 10 / 0
except:
    print("حدث خطأ")

هذا الكود يخفي نوع المشكلة. الأفضل:

try:
    result = 10 / 0
except ZeroDivisionError:
    print("لا يمكن القسمة على صفر")
{alertSuccess} كلما كان التعامل مع الخطأ محددًا، كان الكود أوضح وأسهل في الإصلاح. لا تلتقط كل الأخطاء إذا كنت تعرف نوع الخطأ المتوقع.

أخطاء شائعة عند حل ZeroDivisionError

  • إرجاع صفر دائمًا: قد يخفي مشكلة في البيانات، خصوصًا في النسب والمتوسطات.
  • استخدام except بدون نوع الخطأ: يجعل معرفة سبب المشكلة أصعب.
  • نسيان باقي القسمة: الخطأ قد يظهر مع % وليس مع / فقط.
  • فحص الرقم الخطأ: يجب فحص الرقم الموجود بعد علامة القسمة، لا الرقم الأول.
  • حساب متوسط قائمة فارغة: لأن len(list) قد تكون صفرًا.

مراجعة سريعة للحل

قبل أن تستخدم القسمة في بايثون، اسأل نفسك:

  • هل المقسوم عليه يمكن أن يكون صفرًا؟
  • هل القيمة قادمة من المستخدم؟
  • هل القائمة التي أحسب متوسطها قد تكون فارغة؟
  • هل أستخدم / أو // أو %؟
  • هل أحتاج إلى شرط قبل القسمة أم إلى try except؟

روابط مفيدة من بايثون العرب

مصادر خارجية موثوقة

الخلاصة

خطأ ZeroDivisionError: division by zero في بايثون يعني أن البرنامج حاول قسمة رقم على صفر. الحل ليس أن تخفي الخطأ فقط، بل أن تفهم لماذا أصبحت قيمة المقسوم عليه صفرًا.

إذا كانت القيمة واضحة داخل الكود، استخدم شرطًا قبل القسمة. وإذا كانت القيمة قادمة من المستخدم أو من ملف أو من مصدر خارجي، استخدم try و except مع رسائل واضحة. وعند حساب المتوسط أو النسب، انتبه من القوائم الفارغة والقيم التي قد تساوي صفرًا.

{alertSuccess} الحل العملي: افحص المقسوم عليه قبل القسمة، ولا تستخدم try except لإخفاء المشكلة فقط. اجعل رسالة الخطأ مفهومة، واجعل الكود يمنع القسمة على صفر قبل حدوثها متى أمكن.

أسئلة شائعة

ما سبب خطأ ZeroDivisionError: division by zero؟

السبب هو محاولة قسمة رقم على صفر في بايثون، مثل 10 / 0 أو استخدام متغير قيمته صفر بعد علامة القسمة.

كيف أحل خطأ division by zero في بايثون؟

افحص قيمة المقسوم عليه قبل القسمة باستخدام شرط مثل if divider != 0، أو استخدم try و except ZeroDivisionError إذا كانت القيمة غير مضمونة.

ما معنى float division by zero؟

تعني أن القسمة حدثت باستخدام أعداد عشرية وكان المقسوم عليه صفرًا، مثل 10.0 / 0.0.

لماذا يظهر integer division or modulo by zero؟

تظهر هذه الرسالة غالبًا عند استخدام القسمة الصحيحة // أو باقي القسمة % مع صفر في الجهة اليمنى.

هل أستخدم try except أم if لحل الخطأ؟

استخدم if عندما تستطيع فحص القيمة قبل القسمة، واستخدم try except عندما تكون القيمة قادمة من المستخدم أو من مصدر خارجي وقد تسبب خطأ أثناء التشغيل.

هل يمكن جعل القسمة على صفر تعطي صفرًا؟

يمكنك برمجيًا إرجاع صفر بدل الخطأ، لكن هذا ليس مناسبًا دائمًا. في بعض الحالات الأفضل إرجاع None أو عرض رسالة واضحة حتى لا تخفي مشكلة في البيانات.

إرسال تعليق

أحدث أقدم