الحساب — القسمة والباقي وفخ الأعداد العشرية
العوامل الحسابية السبعة، وأيها يُنفَّذ أولاً، وأين تفيد القسمة الصحيحة وباقي القسمة، ولماذا تعطي الأعداد العشرية أحياناً إجابات غريبة.
كيف تريد أن تتعلم؟
المشكلة التي نقوم بحلها
لديك 17 كتاباً، والصندوق يتسع لـ 5. كم صندوقاً تحتاج، وكم كتاباً يبقى خارجها؟
الجواب ليس 17 / 5. فهذا يعطي 3.4، ولا يوجد شيء اسمه 3.4 صندوق. تحتاج إلى جوابين منفصلين: كم صندوقاً كاملاً وكم يتبقى. في بايثون عامل (operator) لكل منهما، وهما من أكثر العوامل فائدة على الإطلاق — تقسيم الصفحات، وتحويل الثواني إلى ساعات ودقائق، ومعرفة هل العدد زوجي، كلها تأتي من هنا.
وهناك شيء ثانٍ يوقف الجميع أول مرة يرونه: في بايثون، 0.1 + 0.2 لا تعطي 0.3. لماذا لا تعطيها، وماذا تفعل حيال ذلك، هو أيضاً في هذا الفصل.
في نهاية هذا الفصل ستستطيع
- استخدام العوامل الحسابية السبعة
- معرفة أي عملية حسابية تُنفَّذ أولاً، ومتى تحتاج إلى الأقواس
- التعرف على المواضع التي يكون فيها
//و%الأداة المناسبة - شرح لماذا يعطي
/دائماً عدداً عشرياً، حتى عندما تكون القسمة تامة - كتابة حسابات تراعي حدود دقة الأعداد العشرية
المتطلبات المسبقة: المتغيرات والأنواع.
العوامل السبعة
print(10 + 3)
print(10 - 3)
print(10 * 3)
print(10 / 3)
print(10 // 3)
print(10 % 3)
print(10 ** 3)13
7
30
3.3333333333333335
3
1
1000العوامل الثلاثة الأخيرة تحتاج إلى توضيح:
//— القسمة الصحيحة (floor division). تقسم وتحتفظ بالجزء الصحيح، وتتخلص من الباقي%— باقي القسمة (modulo). ما يتبقى بعد القسمة**— الأس (power).10 ** 3تعني عشرة مكعبة
/يعطي دائماً عدداً عشرياً. حتى10 / 5تعطي2.0وليس2. لو كان النوع يعتمد على كون القسمة تامة أم لا، لأصبح سلوك البرنامج غير متوقع، لذلك يلتزم بايثون هنا بقاعدة واحدة:/تعنيfloat. عندما تحتاج إلى عدد صحيح، استخدم//.
حل مشكلة الصناديق
books = 17
per_box = 5
full_boxes = books // per_box
left_over = books % per_box
print("Full boxes:", full_boxes)
print("Left over :", left_over)Full boxes: 3
Left over : 2تمتلئ ثلاثة صناديق ويبقى كتابان خارجها. // و% يأتيان معاً — أحدهما يقول "كم كاملاً"، والآخر "كم يتبقى".
والزوج نفسه يظهر في أماكن كثيرة أخرى:
total_seconds = 500
minutes = total_seconds // 60
seconds = total_seconds % 60
print(minutes, "min", seconds, "sec")8 min 20 secو% هي الطريقة لمعرفة الزوجي والفردي. اقسم أي عدد على 2 فيكون الباقي 0 (زوجي) أو 1 (فردي):
print(14 % 2)
print(15 % 2)0
1هذا الباقي هو بالضبط ما سيبني عليه فصل لاحق عن الشروط (if).
أي عملية حسابية تُنفَّذ أولاً
يتبع بايثون قواعد الحساب المعتادة — الضرب والقسمة قبل الجمع والطرح:
print(10 + 5 * 2)
print((10 + 5) * 2)20
30في السطر الأول نُفّذ 5 * 2 أولاً، ثم أُضيفت 10. وفي السطر الثاني غيّرت الأقواس الترتيب.
من الأعلى أولوية إلى الأدنى:
***و/و//و%+و-
print(2 + 3 * 4 ** 2)504 ** 2 تساوي 16، ثم 3 * 16 تساوي 48، ثم 2 + 48 تساوي 50.
عند الشك، استخدم الأقواس. حتى مع معرفة القواعد، كتابة(a + b) / 2أفضل منa + b / 2— فالشخص التالي الذي يقرأ الكود لا يحتاج إلى تذكّر أي قاعدة. الأقواس الزائدة لا تبطئ الكود؛ بل تجعله أوضح فقط.
هذا أكثر أخطاء المبتدئين شيوعاً، ويظهر عند حساب المتوسط:
a = 10
b = 20
c = 30
wrong = a + b + c / 3
right = (a + b + c) / 3
print("Wrong:", wrong)
print("Right:", right)Wrong: 40.0
Right: 20.0لم يعطِ البرنامج أي خطأ. لا شيء باللون الأحمر، ولا شيء تعطّل — فقط إجابة خاطئة. هذا أخطر أنواع الأخطاء البرمجية (bugs)، لأن بايثون لن يحذّرك. وحده تحققك أنت من الحساب يكشفه.
فخ الأعداد العشرية
print(0.1 + 0.2)0.30000000000000004هذا ليس خطأ بايثون. الحواسيب تخزّن الأعداد بالنظام الثنائي، و0.1 لا يمكن كتابته بدقة في النظام الثنائي — تماماً كما لا يمكن كتابة 1/3 بدقة في النظام العشري، حيث يستمر 0.3333... بلا نهاية. لذلك يخزّن الحاسوب قيمة قريبة جداً، وعند جمع قيمتين من هذا النوع يظهر الفرق الصغير. JavaScript وJava وC كلها تتصرف بالطريقة نفسها.
نتيجتان عمليتان:
الأولى — قرّب الرقم عند العرض:
total = 0.1 + 0.2
print(round(total, 2))0.3round(total, 2) تعني الاحتفاظ بمنزلتين بعد الفاصلة العشرية.
الثانية — لا تقارن عددين عشريين بـ == أبداً:
print(0.1 + 0.2 == 0.3)Falseهذا هو الفخ الذي ينتج إجابات خاطئة في الحسابات المالية. المشاريع الجادة لا تحفظ المال في float — بل تخزّن أصغر وحدة كعدد صحيح (49.99 تصبح 4999)، أو تستخدم الوحدة المنفصلة decimal. الآن اعرف فقط أين الحد؛ الوحدات (modules) تأتي لاحقاً.
مثال كامل
packing.py:
# Work out packing and shipping for one order
total_items = 47
items_per_box = 6
box_cost = 35.5
full_boxes = total_items // items_per_box
loose_items = total_items % items_per_box
# A partly filled box still costs a full box
boxes_needed = full_boxes
if loose_items > 0:
boxes_needed = full_boxes + 1
shipping = boxes_needed * box_cost
print("Items :", total_items)
print("Full boxes :", full_boxes)
print("Loose items :", loose_items)
print("Boxes needed :", boxes_needed)
print("Shipping :", round(shipping, 2))Items : 47
Full boxes : 7
Loose items : 5
Boxes needed : 8
Shipping : 284.0سطر if لم يُشرح بعد — فهذا موضوع الفصول القليلة القادمة. الآن اقرأه فقط: إذا بقيت أي قطع خارج الصناديق، فهناك حاجة إلى صندوق إضافي.
عندما يحدث خطأ
ZeroDivisionError: division by zero قُسم شيء على صفر. هذا غير معرَّف في الرياضيات أيضاً، لذلك يتوقف بايثون. يجب أن تتحقق من المقسوم عليه قبل القسمة — وهذا يصبح سهلاً بعد أن تتعلم الشروط.
10 / 5 أعطت 2.0 وأنا أحتاج إلى 2 استخدم //، أو اكتب int(10 / 5). الأول أفضل: فالقصد واضح في الكود.
// تعطي نتيجة غريبة مع الأعداد السالبة -7 // 2 تعطي -4 وليس -3. بايثون يقرّب إلى الأسفل، لا نحو الصفر. تذكّر هذا إذا كنت تعمل مع الأعداد السالبة.
الحساب يبدو صحيحاً لكن الإجابة خاطئة عُدّ الأقواس، وقسّم كل خطوة على سطر خاص بها واطبعها. الخطأ يكون دائماً تقريباً في ترتيب العمليات.
ذيل طويل من الأرقام بعد الفاصلة العشرية هذا ليس خطأ، بل هو سلوك الأعداد العشرية. اختصره بـ round() عند العرض.
الخطوة ٤ من ٦ — التوقع
تحقّق من فهمك
الأسطر الثلاثة تعمل على العددين نفسيهما، مع عامل مختلف في كل مرة. ما المخرجات؟
print(7 / 2)
print(7 // 2)
print(7 % 2)- A3 3 1
- B3.5 4 1
- C3.5 3.5 1
- D3.5 3 1
يعمل البرنامج دون أي خطأ، لكنه يعطي المتوسط 40.0. لماذا؟
a = 10
b = 20
c = 30
average = a + b + c / 3
print("Average:", average)- A`average` كلمة مفتاحية في بايثون، لذلك لم تُخزَّن القيمة بشكل صحيح
- Bيجب استخدام `//` للمتوسط، لا `/`
- C`/` تُنفَّذ أولاً، لذلك قُسم `c` وحده — يجب كتابة `(a + b + c) / 3`
- Dالأعداد الثلاثة من نوع `int`، وهذا يجعل النتيجة خاطئة
ما مخرجات هذين السطرين؟
print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)- A0.3 True
- B0.3 False
- C0.30000000000000004 False
- D0.30000000000000004 True
الإجابة تتطلب حساباً
سجّل الدخول للتحقق من إجاباتك
الأسئلة موجودة أعلاه، والتفكير في إجاباتها ذهنياً هو الجزء المهم. سجّل الدخول لرؤية الإجابات والتفسيرات والتلميحات ذات المستويات الثلاثة.
دورك الآن
اكتب ملفاً باسم time_split.py يقسم عدداً من الثواني إلى ساعات ودقائق وثوانٍ.
ابدأ من total_seconds = 7385، ويجب أن تكون المخرجات:
2 h 3 m 5 sثلاثة شروط:
- استخدم
//و%فقط — لا تكتب أي نتيجة بيدك - احفظ القيم الثلاث في ثلاثة متغيرات منفصلة ذات أسماء واضحة المعنى
- ثم غيّر
total_secondsإلى59و60و3600و86399وشغّل كلاً منها — وتحقق أن النتائج الأربع صحيحة
لا تتخطَّ الخطوة الأخيرة. البرنامج الذي يعمل مع مدخل واحد لا يعني أنه يعمل؛ البرنامج الذي يصمد أيضاً عند الحدود هو الذي يعمل.
في هذه المهمة المزيد
ما قرأته أعلاه هو المهمة كاملة — لم يُحذف منها شيء. يضيف Pro:
- ما يحدث فعلياً في الكواليس — كيف ينفذ بايثون هذا الكود
- الحل الكامل للتمرين مشروحاً خطوة بخطوة
- تمارين إضافية أكثر صعوبة وتحدياً
- أسئلة المقابلات الوظيفية حول هذا الموضوع مع نموذج الإجابة
الخطوة ٦ من ٦
التحدي — اختبار الفصل
عشرة أسئلة متدرجة من السهل إلى الصعب. الأسئلة الأخيرة صعبة عن قصد.
سجّل الدخول لأداء الاختبار