2·1

العمليات الحسابية الأساسية

جافا فيها آلة حاسبة كاملة: الجمع والطرح والضرب والقسمة — بأربع علامات بسيطة.

تخيّل أن المتغيرات أرقام في ذهنك والعمليات هي العلامات الحسابية التي تعرفها من المدرسة: + للجمع، و- للطرح، و* للضرب — نعم، النجمة وليس علامة الضرب المعتادة، لأن لوحة المفاتيح لا تملك × — و/ للقسمة.

نكتب العملية ونضع ناتجها في متغير أو نطبعه مباشرة، وجافا تحسبها فورًا أثناء التنفيذ.

Calculate.java
public class Calculate {    public static void main(String[] args) {        int a = 17;        int b = 5;        System.out.println("Sum: " + (a + b));        System.out.println("Subtraction: " + (a - b));        System.out.println("Multiplication: " + (a * b));        System.out.println("Division: " + (a / b));        double x = 17.0;        System.out.println("Decimal division: " + (x / b));        System.out.println("No parentheses: " + (2 + 3 * 4));        System.out.println("With parentheses: " + ((2 + 3) * 4));    }}

انتبه لهذه الفخاخ الثلاثة

  • الضرب يستخدم النجمة * والقسمة الشرطة المائلة / — لا يوجد × أو ÷ على لوحة المفاتيح.
  • الأولوية كما في الرياضيات: الضرب والقسمة قبل الجمع والطرح — لذلك 2 + 3 * 4 تعطي 14 وليس 20.
  • الأقواس ( ) لها أعلى أولوية وتغيّر النتيجة تمامًا كما في الرياضيات.
انتبهقسمة عدد صحيح على عدد صحيح تُلقي الكسر بعيدًا! 17 / 5 تعطي 3 وليست 3.4 — لأن النوع int لا يعرف الكسور. إذا أردت الناتج العشري اجعل أحد الطرفين double مثل 17.0 / 5 فتعطي 3.4. شغّل المثال أعلاه وراقب الفرق بنفسك.

مثال واقعي: متوسط الدرجات

ثلاث درجات في المتغيرات — لاحظ أن كل العمليات هنا على أعداد صحيحة، فماذا يحدث للمتوسط؟

GradesAverage.java
public class GradesAverage {    public static void main(String[] args) {        int sum = 20 + 15 + 18;        int count = 3;        int average = sum / count;        System.out.println("Sum: " + sum);        System.out.println("Average: " + average);    }}
لاحظ الناتجالمتوسط الحقيقي لـ 20 و15 و18 هو 17.666... لكن البرنامج طبع 17! القسمة تمت بين قيمتين int فرُميت الكسور قبل التخزين — حتى لو خزّنت الناتج في double فالكسر كان قد ضاع بالفعل. الحل نفسه الذي رأيته أعلاه في هذا الدرس (2·1): اجعل أحد طرفي القسمة عشريًا مثل sum / 3.0 فيُحسب المتوسط كاملًا.
تلميحلاحظ أننا وضعنا العمليات داخل أقواس داخل println: "Sum: " + (a + b) — لولاها لالتصق النص بالرقم. الأقواس تقول لجافا: احسبي العملية أولًا ثم ادمجي الناتج مع النص.
اختبر نفسك · +5 نقاط
ما نتيجة 7 / 2 إذا كان كلاهما int ؟
اختبر نفسك ٢ · حتى +5 نقاط
ما ناتج هذا الكود؟
int a = 17;
double x = 17.0;
System.out.println(a / 5);
System.out.println(x / 5);
اختبر نفسك ٣ · حتى +5 نقاط
كتب طالب double avg = (7 + 8) / 2; وتوقع أن يظهر 7.5، لكن البرنامج طبع 7.0 — ما سبب الخطأ؟
2·2

باقي القسمة %

رمز صغير غير مألوف في الرياضيات، لكنه من أقوى أدوات المبرمج — اسأل أي طالب وزّع 23 طالبًا على مجموعات.

تخيّل أن عندك 23 طالبًا وتريد تكوين مجموعات من 5: تكوّن 4 مجموعات كاملة، ويتبقى 3 طلاب. العملية % تعطيك الباقي فقط: 23 % 5 النتيجة 3. ويقابلها / التي تعطي عدد المجموعات الكاملة: 23 / 5 النتيجة 4.

اقرأ السطرين معًا: «القسمة تقول كم مجموعة كاملة تكوّن، والباقي يقول كم يتبقى خارجها».

23 طالبًا في مجموعات من 5 4 مجموعات كاملة (⁦4 × 5 = 20⁩ نقطة) 3 متبقّية لا تكفي لمجموعة خامسة 23 / 5 = 4 كم مجموعة كاملة؟ 23 % 5 = 3 كم بقي؟ الفردي والزوجي n % 2 = 0 زوجي = 1 فردي مثال: 8 زوجي و 7 فردي
القسمة تعدّ المجموعات الكاملة، و % تعدّ ما بقي خارجها
توقّف وفكّركم يكون 17 % 5 وكم يكون 17 / 5 ؟ فكّر في 17 نقطة موزعة على مجموعات من 5 قبل أن تكشف الإجابة.
اكشف الإجابة17 % 5 تساوي 2، و17 / 5 تساوي 3: تتكوّن 3 مجموعات كاملة (3 × 5 = 15) ويبقى نقطتان (17 - 15 = 2).
Remainder.java
public class Remainder {    public static void main(String[] args) {        System.out.println("10 % 3 = " + (10 % 3));        System.out.println("17 % 5 = " + (17 % 5));        System.out.println("20 % 10 = " + (20 % 10));        int students = 23;        int groupSize = 5;        System.out.println("Complete groups: " + (students / groupSize));        System.out.println("Students left: " + (students % groupSize));        System.out.println("8 % 2 = " + (8 % 2) + " (even)");        System.out.println("7 % 2 = " + (7 % 2) + " (odd)");    }}

أين نستخدم % في البرمجة؟

  • الفردي والزوجي: أي عدد n % 2 ناتجه 0 فهو زوجي وإن كان 1 فهو فردي.
  • التوزيع على مجموعات: معرفة المتبقي بعد توزيع العناصر كما في المثال.
  • استخراج آخر رقم: n % 10 تعطيك الآحاد من أي عدد.
  • الأمر الدوري: اختيار كل ثالث عنصر مثلًا — عندما يكون n % 3 يساوي 0.
انتبهباقي القسمة على صفر مستحيل رياضيًا — جربها بنفسك: عدّل الكود أعلاه واكتب 10 % 0 ثم اضغط «▶ تشغيل» وراقب رسالة الخطأ التي يوقف بها البرنامج التنفيذ.
تلميحمثل القسمة تمامًا: إذا كان أحد الطرفين double يكون الناتج عشريًا. لكن أغلب استخدامات % تكون مع الأعداد الصحيحة.
اختبر نفسك · +5 نقاط
23 طالبًا نوزعهم على مجموعات من 5 — كم طالبًا يتبقى بدون مجموعة كاملة؟

جدول أولوية العمليات — من يُنفَّذ أولًا؟

عندما تجتمع أكثر من عملية في سطر واحد، جافا لا تنفّذها عشوائيًا — بل تتبع جدول أولويات ثابت تحفظه الرياضيات:

الأولويةالعمليةالمعنى
١ — الأعلى( )ما بداخل الأقواس يُحسب دائمًا أولًا، مهما كان حوله
٢*   /   %الضرب والقسمة وباقي القسمة — متساوية فيما بينها، تُنفَّذ من اليسار إلى اليمين
٣+   -الجمع والطرح — تأتي بعد الضرب والقسمة
٤ — الأخيرة=التخزين في المتغير يحدث بعد حساب الطرف الأيمن كاملًا

لاحظ الفرق بين السطرين في هذا البرنامج — نفس الأرقام ونفس العمليات، لكن الأقواس غيّرت كل شيء:

Precedence.java
public class Precedence {    public static void main(String[] args) {        int a = 2 + 3 * 4; // 14: multiplication first        int b = (2 + 3) * 4; // 20: parentheses first        System.out.println(a);        System.out.println(b);    }}
قاعدة ذهبيةعند الشك، استخدم أقواسًا — حتى لو لم تكن ضرورية. الأقواس لا تكلّف شيئًا، وتجعل الكود أوضح لك ولمن يقرأه بعدك.
اختبر نفسك ٢ · حتى +5 نقاط
ما نتيجة System.out.println(10 - 4 / 2); ؟
اختبر نفسك ٣ · حتى +5 نقاط
كتب طالب System.out.println(4 + 6 / 2); وأراد أن يظهر 5، لكنها تطبع 7 — كيف يصحح السطر؟
2·3

معاملا الزيادة والنقصان ++ و --

أسطر مثل count = count + 1 تتكرر كثيرًا في البرامج — فاختصرتها جافا إلى رمزين فقط.

في الألعاب، كلما جمعت نقطة تُحسب هكذا: score = score + 1;. بما أن هذا السطر شائع جدًا، وفّرت جافا اختصارًا: score++; وتعني حرفيًا «أضف 1 على score». ويقابلها score--; لتنقيص 1.

للمعاملين صورتان: بعد المتغير x++ وقبله ++x — والفرق بينهما يظهر فقط عند وضعهما داخل تعبير أكبر (إسناد أو println…)، كما سنرى في المثال.

int x = 5; int y = x++; x 5 6 x = x + 1 y ? 5 القيمة المُرجَعة 5 x = 6 , y = 5 int x = 5; int y = ++x; x = 6 , y = 6 ⁦++x⁩ تزيد x أولًا فتصبح 6، ثم تُرجَع القيمة الجديدة 6 إلى y. int x = 5; x = x++; x = 5 ⁦x++⁩ تُرجِع القيمة القديمة 5، فيكتبها الإسناد فوق الزيادة وتبقى x تساوي 5.
نبدأ بمتغير x قيمته 5 — صندوق واحد فقط حتى الآن. السطر int y = x++; يبدأ بحساب x++ وقيمتها المُرجَعة هي القيمة القديمة 5 (قبل الزيادة). بعد أن حُدّدت القيمة المُرجَعة، تزيد x بمقدار 1 فتصبح 6. الإسناد يضع القيمة المُرجَعة 5 في y: النتيجة النهائية x = 6 و y = 5. المقارنة: ++x تزيد أولًا فتأخذ y القيمة 6؛ أما x = x++; فتُعيد القيمة القديمة 5 فوق الزيادة فتبقى x تساوي 5.

توقّع: في y = x++ هل تأخذ y القيمة قبل الزيادة أم بعدها؟

Counter.java
public class Counter {    public static void main(String[] args) {        int score = 10;        score++;  // same as: score = score + 1;        System.out.println("After increment: " + score);        score++;        System.out.println("After second increment: " + score);        score--;        System.out.println("After decrement: " + score);        int level = 1;        ++level;        System.out.println("New level: " + level);        int box = 7;        int taken = box++;        System.out.println("We took the old value: " + taken);        System.out.println("The box is now: " + box);    }}

اقرأ المثال سطرًا سطرًا

  • score++ تضيف 1 كل مرة — لاحظ القيمة تتغير 10 ثم 11 ثم 12.
  • score-- تُنقص 1 فترجع 12 إلى 11.
  • الصورتان ++x وx++ متطابقتان عندما تكونان أمرًا مستقلًا بذاته.
  • الفرق يظهر فقط داخل تعبير (إسناد أو println…): taken = box++; تضع القيمة القديمة 7 في taken ثم ترفع box إلى 8.
تلميحهذا الدرس مثالي لزر «⏭ تدريجي»: شغّله خطوة خطوة وراقب صناديق المتغيرات — score و box — وهي تتغير أمامك، ثم جرّب «✎ تعديل» وغيّر القيم وشغّل من جديد.
فخّ المحترفين: x = x++تتوقع أن تزداد x بمقدار 1، لكن شغّل المثال وسترى أنها تبقى 5 كما هي! السبب: x++ تعيد القيمة القديمة 5، ثم الإسناد x = ... يكتب هذه القديمة فوق المتغير بعد أن زادته — فيُلغي الزيادة. هذه النتيجة (البقاء على 5) هي سلوك جافا الحقيقية أيضًا، ولهذا يُعتبر السطر بلا معنى عمليًا: إن أردت الزيادة اكتب x++; وحده. عدّل المثال بالأسفل وجرّب بنفسك.
PostfixTrap.java
public class PostfixTrap {    public static void main(String[] args) {        int x = 5;        x = x++;  // trap: the increment is lost!        System.out.println("After x = x++ : " + x);        int y = 5;        y++;  // this is the correct form        System.out.println("After y++ : " + y);    }}
انتبهلا يمكن استخدام ++ أو -- على الثوابت (المتغيرات المعرفة بـ final) — جافا ستوقفك بخطأ واضح، لأن قيمة الثابت لا تتغير أبدًا.
اختبر نفسك · +5 نقاط
إذا كان x = 8 ثم نفّذنا x++; — ما قيمة x بعدها؟
اختبر نفسك ٢ · حتى +5 نقاط
ما ناتج هذا الكود؟
int x = 5;
x++;
x++;
x--;
System.out.println(x);
اختبر نفسك ٣ · حتى +5 نقاط
عرّفنا final int LIMIT = 3; و int level = 1; — أي سطر لاحق يرفضه المترجم؟
★

تحدي: أين الخطأ؟

ثلاثة برامج عن العمليات الحسابية — البرنامج يعمل لكن ناتجه خاطئ أو يرفض التشغيل. اقرأ الكود بتمعّن وتتبّع الناتج سطرًا سطرًا، ثم اضغط على السطر المخالف.

المقطع ١: المتغير double لكن البرنامج يطبع 2.0 بدل 2.5. أين الخطأ؟

public class Test1 { public static void main(String[] args) { double price = 5 / 2; System.out.println("Price: " + price); } }

تتبّع القسمة نفسها قبل التخزين: ما نوع الطرفين اللذين تقسم بينهما؟ وراجع فخ «القسمة الصحيحة» في الدرس 2·1.

المقطع ٢: نريد متوسط عددين لكن الناتج خاطئ. أين الخطأ؟

public class Test2 { public static void main(String[] args) { int a = 10; int b = 20; int avg = a + b / 2; System.out.println("Average: " + avg); } }

احسب ماذا ينفذ أولًا وفق جدول الأولويات، ثم قارن بما نريد فعلًا. الأقواس تملي الترتيب.

المقطع ٣: نريد عدد الطلاب المتبقين خارج المجموعات لكن الناتج 4. أين الخطأ؟

public class Test3 { public static void main(String[] args) { int students = 23; int group = 5; int leftover = students / group; System.out.println("Leftover: " + leftover); } }

«كم مجموعة كاملة نكوّن؟» و«كم يتبقى خارجها؟» — كل سؤال له عملية مختلفة في الدرس 2·2.

لماذا هذا التحدي مهم؟أخطاء العمليات الحسابية لا تُوقف البرنامج — بل تصمت وتُعطي أرقامًا خاطئة. تدريب عينك على تتبّع الناتج سطرًا سطرًا هو بالضبط ما يفعله المبرمج المحترف عند التصحيح — انسخ هذه المقاطع إلى محرر أي درس وشغّلها وقارن الناتج المتوقع بالفعلي.
✎

تمارين الوحدة ٢

تمارين على العمليات الحسابية (الجمع والطرح والضرب والقسمة، باقي القسمة، والزيادة والنقصان). كل تمرين أمامه كود ناقص: اضغط «✎ تعديل»، اكتب الكود المطلوب مكان التعليقات، اضغط «✔ حفظ» ثم «▶ تشغيل» — وقارن نتيجتك بالهدف المكتوب أسفل كل تمرين.

سعر القطعة الواحدة 7 ريالات، والكمية المطلوبة 6 قطع. أكمل البرنامج بسطر واحد: عرّف متغير total يحسب الإجمالي (السعر مضروبًا في الكمية).

Invoice.java
public class Invoice {    public static void main(String[] args) {        int price = 7;        int quantity = 6;        // define total = price * quantity        System.out.println("Total: " + total + " SAR");    }}
الهدف
Total: 42 SAR
تلميحعلامة الضرب في جافا هي * (وليست ×)، والسطر يُكتب مثل أي تعريف متغير: النوع، الاسم، ثم القيمة.

درجات الطالب أربع: 90 و85 و78 و92. أكمل البرنامج: عرّف متغير avg من نوع double يحسب معدل الدرجات الأربع — واحذر فخ القسمة الصحيحة الذي تعلمته في الدرس 2·1!

Average.java
public class Average {    public static void main(String[] args) {        int math = 90;        int science = 85;        int english = 78;        int arabic = 92;        // define avg = sum of grades / count (as a double)        System.out.println("GPA: " + avg);    }}
الهدف
GPA: 86.25
تلميحلو كتبت (math + science + english + arabic) / 4 لحصلت على 86.0 فتخسر الجزء العشري .25! اجعل أحد الطرفين عشريًا: / 4.0.

عندك 23 طالبًا تريد تقسيمهم إلى مجموعات متساوية كل مجموعة فيها 5 طلاب. أكمل المتغيرين الناقصين: groups يخزن عدد المجموعات الكاملة، وleftover يخزن عدد الطلاب المتبقين.

Groups.java
public class Groups {    public static void main(String[] args) {        int students = 23;        int groupSize = 5;        // full groups count in variable groups        // leftover students in variable leftover        System.out.println("Groups: " + groups + " leftover: " + leftover);    }}
الهدف
Groups: 4 leftover: 3
تلميحالقسمة / تعطي عدد المجموعات الكاملة، وباقي القسمة % يعطي المتبقي — استخدم كليهما.

لعبة بدأت بنقاط 10. في الجزء الأول استخدم ++ مرتين ثم -- مرة (ثلاثة أسطر) على المتغير score. في الجزء الثاني اطبع score مرة، ثم اطبع score++ داخل println مباشرة، ثم اطبع score مرة أخيرة — راقب كيف تُطبع القيمة القديمة قبل الزيادة!

ScoreBoard.java
public class ScoreBoard {    public static void main(String[] args) {        int score = 10;        // 1) ++ twice then -- once (three lines)        // 2) print score, then print score++, then print score    }}
الهدف
11
11
12
تلميحبعد الأسطر الثلاثة تكون القيمة 11. السطر الذي يطبع score++ يعرض 11 القديمة ثم يرفع القيمة إلى 12 — لهذا تتكرر 11 مرتين.
أنهيت تمارين الوحدة؟انتقل إلى الصفحة الرئيسية وتابع تقدمك في بطاقات الوحدات، أو راجع دروس الوحدة الثانية من القائمة الجانبية.