الكلية الجامعية للعلوم التطبيقيةبرمجة 1
English
المحاضرة 6 · 100 دقيقة

التعبيرات والتحويل بين الأنواع والدوال الرياضية

لماذا تعطي 5 / 2 القيمة 2، وكيف تجعل Java تحسب ما تقصده تمامًا؟

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

  1. تحسب أي تعبير وفق أولوية العوامل، وتغيّر ترتيبه بالأقواس
  2. تتجنب فخ قسمة الأعداد الصحيحة، خصوصًا في حساب المعدل
  3. تميّز التحويل التلقائي إلى نوع أوسع من التحويل الصريح، وتضع (int) و(double) في مكانهما الصحيح
  4. تحسب بالحروف، وتصرّح عن الثوابت بالكلمة final
  5. تستخدم دوال الصنف Math وتعرف نوع ما تُرجعه كل دالة
  6. تفسّر مفاجآت الأعداد العشرية والفيضان، وتوظّف % في مسائل حقيقية
محتويات المحاضرة
  1. الضرب يسبق الجمع، والأقواس تسبق الجميع
  2. قسمة عددين صحيحين تعطي عددًا صحيحًا، ويُحذف الكسر
  3. صندوق double لا ينقذ قسمة صحيحة انتهت قبل أن تصل إليه
  4. تحوّل Java القيمة تلقائيًا إلى نوع أوسع، لأنها لن تفقد شيئًا
  5. يرفض المترجم وضع double في int لأن الكسر سيضيع
  6. التحويل الصريح يقول للمترجم: أعرف ما أفعله
  7. مكان التحويل يحدد هل ينجو الكسر أم لا
  8. يخزّن char رقمًا في الحقيقة، ولذلك يمكن الحساب به
  9. final تجعل القيمة ثابتة، ونكتب اسمها بأحرف كبيرة
  10. الصنف Math جاهز للحسابات الصعبة، ولا يحتاج إلى استيراد
  11. round وceil وfloor ثلاث طرق مختلفة لإزالة الكسر
  12. 0.1 + 0.2 لا تساوي 0.3 تمامًا، وprintf تخفي الفرق
  13. يفيض int بصمت حتى في منتصف الحساب
  14. % تجيب عن أسئلة حقيقية: زوجي؟ آخر رقم؟ كم ثانية بقيت؟
  15. التمرين النهائي: معدل ثلاث علامات وأعلاها
  16. أسئلة المراجعة
الجزء الأول: كيف تحسب Java؟

الضرب يسبق الجمع، والأقواس تسبق الجميع

الأولويةالعواملالترتيب بين المتساوية
الأولى( )من الداخل إلى الخارج
الثانية++ -- (int) (double)من اليمين إلى اليسار
الثالثة* / %من اليسار إلى اليمين
الرابعة+ -من اليسار إلى اليمين
الأخيرة= += -= *= /=من اليمين إلى اليسار

احسب كل سطر على الورق أولًا. ماذا يطبع البرنامج؟

public class Precedence {
    public static void main(String[] args) {
        System.out.println(2 + 3 * 4);
        System.out.println((2 + 3) * 4);
        System.out.println(20 / 2 * 5);
        System.out.println(20 / (2 * 5));
        System.out.println(10 + 7 % 3);
    }
}
أظهر الناتج
الناتج
14
20
50
2
11

لماذا؟ * قبل +، والأقواس تعكس ذلك. و/ و* متساويان، فنبدأ من اليسار: 20 ÷ 2 = 10، ثم × 5 = 50. و% في مستوى الضرب: 7 % 3 = 1، ثم 10 + 1.

زوج من الأقواس يغيّر الجواب

ما معدل 80 و90؟ قارن بين السطرين، ثم غيّر القيمتين إلى 60 و100 وتوقّع الناتج قبل التشغيل.

public class Average {
    public static void main(String[] args) {
        int a = 80;
        int b = 90;
        System.out.println(a + b / 2);
        System.out.println((a + b) / 2);
    }
}
الناتج
125
85

قسمة عددين صحيحين تعطي عددًا صحيحًا، ويُحذف الكسر

تقرر Java نوع النتيجة من نوع الطرفين قبل أن تحسب: int / int يعطي int. فإذا كان أحد الطرفين double، كانت النتيجة double.

الأرقام متقاربة، لكن النتائج ليست كذلك. ماذا يطبع البرنامج؟

public class Division {
    public static void main(String[] args) {
        System.out.println(5 / 2);
        System.out.println(5.0 / 2);
        System.out.println(5 / 2.0);
        System.out.println(1 / 2);
    }
}
أظهر الناتج
الناتج
2
2.5
2.5
0

لماذا؟ الكسر يُحذف ولا يُقرَّب: 5 / 2 تعطي 2 لا 3. ويكفي أن يكون طرف واحد double لتبقى النتيجة بكسرها.

البيتزا والأصدقاء

وزّع 7 قطع على 4 أصدقاء. جرّب قيمًا أخرى، وابحث عن حالة تطبع فيها القسمة الصحيحة 0.

public class Pizza {
    public static void main(String[] args) {
        int slices = 7;
        int friends = 4;
        System.out.println(slices / friends);
        System.out.println(slices % friends);
        System.out.println(slices / 4.0);
    }
}
الناتج
1
3
1.75

ما قيمة 9 / 10؟

صندوق double لا ينقذ قسمة صحيحة انتهت قبل أن تصل إليه

المعدل الحقيقي للعددين 4 و5 هو 4.5. ماذا يطبع البرنامج؟

public class AverageTrap {
    public static void main(String[] args) {
        int a = 4;
        int b = 5;
        double average = (a + b) / 2;
        System.out.println(average);
    }
}
أظهر الناتج
الناتج
4.0

لماذا؟ يُحسب الجانب الأيمن أولًا دون النظر إلى نوع الصندوق: 9 / 2 = 4 قسمة صحيحة. بعد ذلك فقط تُخزَّن 4 في double فتصبح 4.0. لقد ضاع الكسر قبل الوصول إلى الصندوق.

الإصلاح الأسهل: اجعل المقسوم عليه 2.0

غيّر 2.0 إلى 2 ولاحظ الفرق. ثم أضف عددًا ثالثًا c وعدّل المعادلة.

public class AverageFixed {
    public static void main(String[] args) {
        int a = 4;
        int b = 5;
        double average = (a + b) / 2.0;
        System.out.println(average);
    }
}
الناتج
4.5
الجزء الثاني: التحويل بين الأنواع

تحوّل Java القيمة تلقائيًا إلى نوع أوسع، لأنها لن تفقد شيئًا

يتسع double لأي قيمة في int، ويتسع int لرمز أي char. لذلك تنقل Java القيمة إلى الصندوق الأوسع دون أن تطلب منها ذلك، ويسمى هذا التحويل التلقائي. ترتيب الأنواع من الأضيق إلى الأوسع: char ثم int ثم long ثم double.

whole7int
decimal7.0double

التحويل التلقائي أثناء العمل

اضغط «تتبّع سطرًا سطرًا» وقارن قيمتي الصندوقين whole وdecimal.

public class Widening {
    public static void main(String[] args) {
        int whole = 7;
        double decimal = whole;
        System.out.println(decimal);
        System.out.println(whole + 0.5);

        char letter = 'A';
        int code = letter;
        System.out.println(code);
    }
}
الناتج
7.0
7.5
65

ما نوع نتيجة 3 + 2.0؟

يرفض المترجم وضع double في int لأن الكسر سيضيع

التحويل التلقائي يسير في اتجاه واحد. إذا كان الاتجاه قد يُضيّع جزءًا من القيمة، أوقفك المترجم وطلب منك أن تقرر بنفسك.

سعر في صندوق صحيح

نريد الاحتفاظ بالسعر كاملًا. أصلح نوع المتغير حتى يطبع البرنامج 12.75.

public class Price {
    public static void main(String[] args) {
        double price = 12.75;
        int copy = price;
        System.out.println(copy);
    }
}
رسالة المترجمincompatible types: possible lossy conversion from double to int
أظهر التصحيح
public class Price {
    public static void main(String[] args) {
        double price = 12.75;
        double copy = price;
        System.out.println(copy);
    }
}
الناتج
12.75

لماذا؟ «lossy» تعني أن هناك ما قد يضيع، وهو هنا .75. ويرفض المترجم السطر حتى لو كانت القيمة 12.0، لأنه ينظر إلى النوع لا إلى القيمة.

أي سطر يرفضه المترجم؟

التحويل الصريح يقول للمترجم: أعرف ما أفعله

(int) يحذف الكسر

لا يقرّب أبدًا: 12.99 تصبح 12، و-3.99 تصبح -3.

int whole = (int) 12.99;
(double) يضيف الكسر

لا تتغير القيمة، لكن نوعها يتغير، فتتغير طريقة الحساب بها.

double d = (double) 5;

جرّب التحويل الصريح

لاحظ أن price لم يتغير بعد التحويل: التحويل ينشئ قيمة جديدة، ولا يبدّل الصندوق الأصلي. اضغط «تتبّع سطرًا سطرًا» وتأكد.

public class Casts {
    public static void main(String[] args) {
        double price = 12.99;
        int whole = (int) price;
        System.out.println(whole);
        System.out.println(price);
        System.out.println((int) -3.99);
        System.out.println((double) 5);
    }
}
الناتج
12
12.99
-3
5.0

الفرق زوج من الأقواس. ماذا يطبع البرنامج؟

public class CastScope {
    public static void main(String[] args) {
        System.out.println((int) 3.7 + 0.9);
        System.out.println((int) (3.7 + 0.9));
    }
}
أظهر الناتج
الناتج
3.9
4

لماذا؟ للتحويل أولوية أعلى من الجمع، فهو يمس القيمة التالية له فقط. في السطر الأول يصبح 3.7 العدد 3، ثم + 0.9. وفي الثاني تُجمع القيمتان أولًا فنحصل على 4.6، ثم يُحذف الكسر.

مكان التحويل يحدد هل ينجو الكسر أم لا

ثلاثة أماكن للتحويل نفسه. ماذا يطبع البرنامج؟

public class CastPlace {
    public static void main(String[] args) {
        int a = 5;
        int b = 2;
        System.out.println((double) a / b);
        System.out.println(a / (double) b);
        System.out.println((double) (a / b));
    }
}
أظهر الناتج
الناتج
2.5
2.5
2.0

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

معدل في صندوق صحيح

نريد حذف الكسر عمدًا والاحتفاظ بالجزء الصحيح من المعدل. استخدم تحويلًا صريحًا حتى يطبع البرنامج 4.

public class WholeAverage {
    public static void main(String[] args) {
        int sum = 9;
        int average = sum / 2.0;
        System.out.println(average);
    }
}
رسالة المترجمpossible lossy conversion from double to int
أظهر التصحيح
public class WholeAverage {
    public static void main(String[] args) {
        int sum = 9;
        int average = (int) (sum / 2.0);
        System.out.println(average);
    }
}
الناتج
4

لماذا؟ sum / 2.0 من نوع double، فلا تدخل في int دون إذن. لاحظ الأقواس: دونها يطبق التحويل على sum وحده، وتبقى النتيجة double فيبقى الخطأ.

معدل دقيق لعددين صحيحين

اطبع First: واقرأ عددًا صحيحًا في متغير int، ثم Second: واقرأ عددًا صحيحًا آخر. ثم اطبع Average: متبوعة بالمعدل الدقيق، باستخدام تحويل صريح.

import java.util.Scanner;

public class ExactAverage {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read two int values, then print their exact average

    }
}
stdin
4
5
الناتج المتوقع
First: Second: Average: 4.5
تلميح 1

اجمع أولًا داخل أقواس، ثم حوّل المجموع: (double) (a + b).

تلميح 2

إذا طبع البرنامج 4.0 فالتحويل جاء بعد القسمة.

الحل
import java.util.Scanner;

public class ExactAverage {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("First: ");
        int a = input.nextInt();
        System.out.print("Second: ");
        int b = input.nextInt();
        double average = (double) (a + b) / 2;
        System.out.println("Average: " + average);
    }
}

يخزّن char رقمًا في الحقيقة، ولذلك يمكن الحساب به

الحرفالرمز
'A'65
'B'66
'a'97
'0'48

الحساب بالحروف

غيّر letter إلى 'Z' ثم إلى 'a'، وتوقّع الناتج قبل كل تشغيل.

public class CharMath {
    public static void main(String[] args) {
        char letter = 'A';
        System.out.println(letter + 1);
        System.out.println((char) (letter + 1));
        letter++;
        System.out.println(letter);
        System.out.println('7' - '0');
        System.out.println('a' - 'A');
    }
}
الناتج
66
B
B
7
32

أين الفرق بين السطرين؟

public class CharPlus {
    public static void main(String[] args) {
        System.out.println('A' + 'B');
        System.out.println("" + 'A' + 'B');
    }
}
أظهر الناتج
الناتج
131
AB

لماذا؟ + بين حرفين تعني جمعهما عددين: 65 + 66. أما مع نص، ولو كان فارغًا، فتعني الدمج. ولأن Java تقرأ من اليسار إلى اليمين، يصبح الناتج نصًا بعد الخطوة الأولى، فيُدمج الحرف الثاني أيضًا.

الحرف التالي

نريد الحرف الذي يلي A. أصلح السطر حتى يطبع البرنامج B.

public class NextLetter {
    public static void main(String[] args) {
        char letter = 'A';
        char next = letter + 1;
        System.out.println(next);
    }
}
رسالة المترجمpossible lossy conversion from int to char
أظهر التصحيح
public class NextLetter {
    public static void main(String[] args) {
        char letter = 'A';
        char next = (char) (letter + 1);
        System.out.println(next);
    }
}
الناتج
B

لماذا؟ char + int يعطي int، وint أوسع من char، فنحتاج إلى تحويل صريح. وهذا هو الخطأ نفسه الذي رأيناه مع double، باتجاه آخر من الأنواع.

الجزء الثالث: الثوابت و`Math` والمفاجآت

final تجعل القيمة ثابتة، ونكتب اسمها بأحرف كبيرة

الرقم 0.16 في وسط معادلة لا يقول شيئًا لمن يقرؤه. أما TAX_RATE فتشرح نفسها، وإذا تغيرت الضريبة فسنعدّل سطرًا واحدًا.

ثابت واحد يُستخدم عدة مرات

غيّر قيمة TAX_RATE إلى 0.2 في سطر واحد، ولاحظ كيف تتغير كل النتائج.

public class Tax {
    public static void main(String[] args) {
        final double TAX_RATE = 0.16;
        double price = 100.0;
        double tax = price * TAX_RATE;
        System.out.println(tax);
        System.out.println(price + tax);
    }
}
الناتج
16.0
116.0
الاسمالاستخدامالقاعدة
studentAgeمتغيرcamelCase
TAX_RATEثابتأحرف كبيرة، وبين الكلمات _
MAX_STUDENTSثابتأحرف كبيرة، وبين الكلمات _

الثابت لا يتغير

لا نريد تغيير الضريبة هنا. احذف السطر الذي يخالف ذلك.

public class FinalRate {
    public static void main(String[] args) {
        final double TAX_RATE = 0.16;
        TAX_RATE = 0.2;
        System.out.println(TAX_RATE);
    }
}
رسالة المترجمcannot assign a value to final variable TAX_RATE
أظهر التصحيح
public class FinalRate {
    public static void main(String[] args) {
        final double TAX_RATE = 0.16;
        System.out.println(TAX_RATE);
    }
}
الناتج
0.16

لماذا؟ هذه فائدة final: يمنعك المترجم من تغيير القيمة بالخطأ، بدل أن تكتشف ذلك من نتائج خاطئة لاحقًا.

الصنف Math جاهز للحسابات الصعبة، ولا يحتاج إلى استيراد

الاستخدامالمعنىالناتجالنوع
Math.pow(2, 10)2 أس 101024.0double
Math.sqrt(16)الجذر التربيعي4.0double
Math.abs(-7)القيمة المطلقة7نوع المعامل
Math.max(3, 9)الأكبر9نوع المعامل
Math.min(3, 9)الأصغر3نوع المعامل
Math.PIثابت جاهز3.141592653589793double

جولة في Math

لاحظ أن Math.PI مكتوب بأحرف كبيرة لأنه ثابت، ودون أقواس لأنه ليس دالة. غيّر القيم وتوقّع الناتج.

public class MathTour {
    public static void main(String[] args) {
        System.out.println(Math.pow(2, 10));
        System.out.println(Math.sqrt(16));
        System.out.println(Math.abs(-7));
        System.out.println(Math.max(3, 9));
        System.out.println(Math.min(3, 9));
        System.out.println(Math.PI);
    }
}
الناتج
1024.0
4.0
7
9
3
3.141592653589793

وتر المثلث القائم

جرّب 3 و4، ثم 5 و12، ثم قيمًا من اختيارك. يعتمد الحساب على a وb كما كتبتهما أنت.

import java.util.Scanner;

public class Hypotenuse {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Side a: ");
        double a = input.nextDouble();
        System.out.print("Side b: ");
        double b = input.nextDouble();
        double c = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
        System.out.println("Hypotenuse: " + c);
    }
}

pow تُرجع double

أصلح السطر بتحويل صريح حتى يطبع البرنامج 8.

public class Power {
    public static void main(String[] args) {
        int result = Math.pow(2, 3);
        System.out.println(result);
    }
}
رسالة المترجمpossible lossy conversion from double to int
أظهر التصحيح
public class Power {
    public static void main(String[] args) {
        int result = (int) Math.pow(2, 3);
        System.out.println(result);
    }
}
الناتج
8

لماذا؟ القيمتان 2 و3 عددان صحيحان، لكن ما يحدد النوع هو ما تُرجعه الدالة: Math.pow تُرجع double دائمًا.

round وceil وfloor ثلاث طرق مختلفة لإزالة الكسر

الدالةتفعل2.12.5-2.5تُرجع
Math.roundإلى الأقرب23-2long
Math.ceilإلى الأعلى3.03.0-2.0double
Math.floorإلى الأسفل2.02.0-3.0double
(int)حذف الكسر22-2int

قارن بين الطرق. ماذا يطبع البرنامج؟

public class Rounding {
    public static void main(String[] args) {
        double value = 2.7;
        System.out.println(Math.round(value));
        System.out.println(Math.ceil(value));
        System.out.println(Math.floor(value));
        System.out.println((int) value);
    }
}
أظهر الناتج
الناتج
3
3.0
2.0
2

لماذا؟ round تعطي عددًا صحيحًا، وceil وfloor تعطيان double دائمًا، ولذلك يظهر .0. ولا تخلط بين floor و(int): يتفقان في الأعداد الموجبة ويختلفان في السالبة.

متى نحتاج إلى ceil؟

23 طالبًا، وفي كل سيارة 4 مقاعد. كم سيارة نحتاج؟ لاحظ (double) قبل القسمة. ثم غيّر عدد الطلاب إلى 21 وبدّل ceil إلى round: لماذا يبقى طالب دون مقعد؟

public class Cars {
    public static void main(String[] args) {
        int students = 23;
        int seats = 4;
        double cars = Math.ceil((double) students / seats);
        System.out.println(cars);
    }
}
الناتج
6.0

مساحة الدائرة

اطبع Radius: واقرأ نصف القطر عددًا عشريًا، ثم اطبع Area: متبوعة بالمساحة برقمين عشريين. استخدم Math.PI وMath.pow.

import java.util.Scanner;

public class CircleArea {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read the radius, calculate the area, print with printf

    }
}
stdin
1
الناتج المتوقع
Radius: Area: 3.14
تلميح 1

المساحة تساوي Math.PI * Math.pow(radius, 2).

تلميح 2

استخدم القالب "Area: %.2f%n".

الحل
import java.util.Scanner;

public class CircleArea {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Radius: ");
        double radius = input.nextDouble();
        double area = Math.PI * Math.pow(radius, 2);
        System.out.printf("Area: %.2f%n", area);
    }
}

0.1 + 0.2 لا تساوي 0.3 تمامًا، وprintf تخفي الفرق

الحاسوب يخطئ في الجمع؟

توقّع السطر الأول قبل التشغيل. لاحظ أن printf غيّرت شكل العرض فقط: السطر الثالث يثبت أن total لم يتغير.

public class FloatSurprise {
    public static void main(String[] args) {
        double total = 0.1 + 0.2;
        System.out.println(total);
        System.out.printf("%.2f%n", total);
        System.out.println(total);
        System.out.println(Math.round(total * 100) / 100.0);
    }
}
الناتج
0.30000000000000004
0.30
0.30000000000000004
0.3

لا يمكن كتابة 1 ÷ 3 في النظام العشري بدقة تامة: 0.333 ثم لا تنتهي. وكذلك لا يمكن كتابة 0.1 بدقة تامة في النظام الثنائي الذي يستخدمه الحاسوب، فيخزَّن أقرب رقم ممكن. هذا سلوك كل لغات البرمجة، وليس خطأ في Java.

printf تقرّب، و(int) تحذف. ماذا يطبع البرنامج؟

public class RoundOrCut {
    public static void main(String[] args) {
        double value = 2.96;
        System.out.printf("%.1f%n", value);
        System.out.println((int) value);
        System.out.println(1.1 * 3);
    }
}
أظهر الناتج
الناتج
3.0
2
3.3000000000000003

لماذا؟ تعرض printf القيمة مقرّبة إلى رقم عشري واحد، بينما يحذف (int) الكسر كله. والسطر الأخير مفاجأة أخرى من النوع نفسه، لأن 1.1 مخزَّنة تقريبيًا أيضًا.

يفيض int بصمت حتى في منتصف الحساب

رأينا في محاضرة المتغيرات أن إضافة 1 إلى أكبر int تعطي عددًا سالبًا. ولا يعترض المترجم على ذلك، ولا يتوقف البرنامج: يظهر رقم خاطئ فقط.

يتسع long لمليون × مليون. ماذا يطبع البرنامج؟

public class Overflow {
    public static void main(String[] args) {
        long wrong = 1000000 * 1000000;
        long right = 1000000L * 1000000;
        System.out.println(wrong);
        System.out.println(right);
    }
}
أظهر الناتج
الناتج
-727379968
1000000000000

لماذا؟ إنه فخ المعدل نفسه: يُحسب الجانب الأيمن قبل النظر إلى الصندوق. فالضرب في السطر الأول int * int ويفيض قبل الوصول إلى long. والحرف L يجعل أحد الطرفين long، فيتم الضرب كله بالنوع الأوسع.

كم ثانية في حياتك؟

السطر الأول يبدو سليمًا، لكنه تجاوز حد int. احذف الحرف L من السطر الثاني وشغّله، ثم عدّل العمر إلى عمرك.

public class Seconds {
    public static void main(String[] args) {
        int age = 100;
        int shortAnswer = age * 365 * 24 * 60 * 60;
        long longAnswer = age * 365L * 24 * 60 * 60;
        System.out.println(shortAnswer);
        System.out.println(longAnswer);
    }
}
الناتج
-1141367296
3153600000

% تجيب عن أسئلة حقيقية: زوجي؟ آخر رقم؟ كم ثانية بقيت؟

زوجي أم فردي

الباقي بعد القسمة على 2 هو 0 للزوجي و1 للفردي.

n % 2
آخر رقم

الباقي بعد القسمة على 10 هو الرقم الأخير، والقسمة الصحيحة على 10 تحذفه.

n % 10
n / 10
دقائق وثوانٍ

القسمة الصحيحة تعطي الدقائق الكاملة، والباقي يعطي الثواني المتبقية.

total / 60
total % 60

فكّك عددًا

اكتب 12345، ثم 7، ثم 100. ما الذي تخبرك به Even check عن العدد؟ ستحتاج إلى هذه الفكرة في شرط if قريبًا.

import java.util.Scanner;

public class Digits {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("A whole number: ");
        int number = input.nextInt();
        System.out.println("Even check: " + number % 2);
        System.out.println("Last digit: " + number % 10);
        System.out.println("Without last digit: " + number / 10);
    }
}

فكّر في كل سطر: ماذا يطبع البرنامج؟

public class ModuloUses {
    public static void main(String[] args) {
        int number = 2468;
        System.out.println(number % 2);
        System.out.println(number % 10);
        System.out.println(number % 100);
        System.out.println(number / 100);
    }
}
أظهر الناتج
الناتج
0
8
68
24

لماذا؟ يعطي % 10 آخر رقم، ويعطي % 100 آخر رقمين. و/ 100 قسمة صحيحة تحذف الرقمين الأخيرين. وكلما زادت الأصفار في العدد الذي نقسم عليه، زاد عدد الأرقام.

دقائق وثوانٍ

اطبع Seconds: واقرأ عددًا صحيحًا، ثم اطبع الناتج بالشكل 3 min 5 sec. فمثلًا 185 ثانية هي 3 دقائق و5 ثوانٍ.

import java.util.Scanner;

public class SplitSeconds {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read the total, split it with / and %, then print

    }
}
stdin
185
الناتج المتوقع
Seconds: 3 min 5 sec
تلميح 1

في كل دقيقة 60 ثانية، فالدقائق هي total / 60.

تلميح 2

الثواني المتبقية هي total % 60.

الحل
import java.util.Scanner;

public class SplitSeconds {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Seconds: ");
        int total = input.nextInt();
        int minutes = total / 60;
        int seconds = total % 60;
        System.out.println(minutes + " min " + seconds + " sec");
    }
}

التمرين النهائي: معدل ثلاث علامات وأعلاها

ملخص العلامات

اقرأ ثلاث علامات صحيحة بالرسائل Mark 1: وMark 2: وMark 3: . ثم اطبع Average: متبوعة بالمعدل برقمين عشريين على سطر، وHighest: متبوعة بأعلى علامة على السطر التالي.

import java.util.Scanner;

public class MarksSummary {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read three marks, then print the average and the highest

    }
}
stdin
80
90
85
الناتج المتوقع
Mark 1: Mark 2: Mark 3: Average: 85.00
Highest: 90
تلميح 1

اقسم على 3.0، وإلا فسيضيع الكسر قبل وصوله إلى printf.

تلميح 2

تأخذ Math.max قيمتين فقط، لكن يمكن وضع إحداهما داخل الأخرى: Math.max(a, Math.max(b, c)).

الحل
import java.util.Scanner;

public class MarksSummary {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Mark 1: ");
        int a = input.nextInt();
        System.out.print("Mark 2: ");
        int b = input.nextInt();
        System.out.print("Mark 3: ");
        int c = input.nextInt();
        double average = (a + b + c) / 3.0;
        int highest = Math.max(a, Math.max(b, c));
        System.out.printf("Average: %.2f%n", average);
        System.out.println("Highest: " + highest);
    }
}

أسئلة المراجعة

أي سطر يعطي معدل a وb بدقة، إذا كان كلاهما int؟

لماذا يرفض المترجم السطر int r = Math.sqrt(16);؟

أي تصريح يتبع العرف الصحيح لثابت؟

اجمع ما تعلمته اليوم. ماذا يطبع البرنامج؟

public class ReviewMixed {
    public static void main(String[] args) {
        int a = 7;
        int b = 2;
        System.out.println(a / b + 0.5);
        System.out.println((double) a / b + 0.5);
        System.out.println(a % b * 10);
    }
}
أظهر الناتج
الناتج
3.5
4.0
10

لماذا؟ السطر الأول: 7 / 2 = 3 قسمة صحيحة، ثم + 0.5. والثاني: (double) a تحوّل قبل القسمة، فتعطي 3.5، ثم + 0.5. والثالث: % و* متساويان، فمن اليسار: 7 % 2 = 1، ثم × 10.