تمرينات

تمرين 9.1
a. ارسم مخططاً هرمياً للبرنامج التالي، يبين المتغيرات المحلية ومعاملات العمليتين main وriddle، وبين أية كائنات تشير إليها هذه المتغيرات.
b. ما هو خرج هذا البرنامج؟
كود:
public static void main (String[] args)
{
  int x = 5;
  Point blank = new Point (1, 2);
 
  System.out.println (riddle(x, blank));
  System.out.println (x);
  System.out.println (blank.x);
  System.out.println (blank.y);
}
 
public static int riddle(int x, Point p)
{
  x = x + 7;
 
  return x + p.x + p.y;
}
إن الغرض من هذا التمرين هو الـتأكد من فهمك لآلية تمرير الكائنات كمعاملات.

تمرين 9.2

a. ارسم مخططاً هرمياً للبرنامج التالي، يبين حالة البرنامج قبيل عودة العملية distance. قم بتضمين كافة المتغيرات والمعاملات والكائنات التي تشير إليها هذه المتغيرات.
b. ما هو خرج هذا البرنامج؟
كود:
public static double distance (Point p1, Point p2) {
  int dx = p1.x - p2.x;
  int dy = p1.y - p2.y;
  return Math.sqrt (dx*dx + dy*dy);
}
 
public static Point findCenter (Rectangle box) {
  int x = box.x + box.width/2;
  int y = box.y + box.height/2;
  return new Point (x, y);
}
 
public static void main (String[] args) {
  Point blank = new Point (5, 8);
 
  Rectangle rect = new Rectangle (0, 2, 4, 4);
  Point center = findCenter (rect);
 
  double dist = distance (center, blank);
 
  System.out.println (dist);
}

تمرين 9.3
العملية grow هي جزء من الصنف الجاهز Rectangle. اقرأ وثائقها على
http://download. oracle. com/javase/6/docs/api/java/awt/
Rectangle.html# grow( int,int)
ثم أجب عن الأسئلة
a. ما هو خرج البرنامج التالي؟
b. ارسم مخطط حالة يبين حالة البرنامج قبيل انتهاء main. قم بتضمين كافة المتغيرات المحلية والكائنات التي تشير إليها.
c. عند نهاية main، هل يشير المتغيرين p1 وp2 إلى الكائن نفسه؟ لماذا أو لم لا؟
كود:
public static void printPoint (Point p) {
   System.out.println ("(" + p.x + ", " + p.y + ")");
}
 
public static Point findCenter (Rectangle box) {
   int x = box.x + box.width/2;
   int y = box.y + box.height/2;
   return new Point (x, y);
}
 
public static void main (String[] args) {
 
   Rectangle box1 = new Rectangle (2, 4, 7, 9);
   Point p1 = findCenter (box1);
   printPoint (p1);
 
   box1.grow (1, 1);
   Point p2 = findCenter (box1);
   printPoint (p2);
}

تمرين 9.4

على الأغلب أنك مرضت من عملية العاملي الآن، لكننا سنعمل نسخة أخرى منها أيضاً.
a. أنشئ برنامجاً باسم Big.java وابدأ بكتابة نسخة تكرارية من factorial.
b. اطبع جدولاً للأعداد الصحيحة من 0 إلى 30 مع عاملي كل منها. عند مكان ما بالقرب من 15، ستلاحظ على الأغلب أن الإجابات لم تعد صحيحة. لم حدث ذلك؟
c. BigIntegers هي كائنات جاهزة في Java يمكنها أن تمثل أعداداً صحيحة ذات حجم اختياري. لا سقف لها سوى محدودية الذاكرة وسرعة المعالجة. اقرأ وثائق صنف BigIntegers من
http://download.oracle.com/javase/6/docs/api/java/math
/BigInteger.html
d. توجد طرق عدة لإنشاء BigInteger جديد، لكنني أنصح بالطريقة التي تستخدم valueOf. الشفرة التالية تحول عدداً صحيحاً إلى BigInteger:
كود:
int x = 17;
BigInteger big = BigInteger.valueOf (x);
اكتب هذه الشفرة وجرب بعض الحالات البسيطة مثل إنشاء BigInteger وطباعته. لاحظ أن println تعرف كيف تطبع الBigIntegers! لا تنسى إضافة import java.math.BigInteger; إلى بداية برنامجك.
e. لسوء الحظ، لا يمكننا استخدام العوامل الرياضية المعتادة على الBigIntegers، لأنها ليست نوعاً بسيطاً. بل يجب علينا استخدام عمليات الكائن مثل add. لجمع كائنين BigInteger معاً، عليك استدعاء add على أحدهما وتمرير الآخر كمتحول. مثلاً:
كود:
BigInteger small = BigInteger.valueOf (17);
BigInteger big = BigInteger.valueOf (1700000000);
BigInteger total = small.add (big);
جرب بعض العمليات الأخرى، مثل multiply وpow.
f. حول factorial حتى تستخدم BigIntegers في حساباتها، ثم تعيد BigInteger كنتيجة. يمكنك ترك المعامل كما هو – سيبقى عدداً صحيحاً.
g. جرب طباعة الجدول ثانية باستخدام تابع العاملي المعدل. هل هو صحيح حتى 30؟ لأي رقم يمكنك حساب العاملي؟ أنا حسبت العاملي لكل الأعداد من 0 حتى 999، لكن جهازي بطيء فعلاً، وقد استغرقت العملية بعض الوقت. آخر رقم، !999، يتألف من 2565 خانة.

تمرين 9.5

العديد من خوارزميات التشفير تعتمد على القدرة على رفع الأعداد الصحيحة الكبيرة إلى قوة صحيحة. إليك عملية تجري خوارزمية سريعة (بشكل معقول) لحساب القوى الصحيحة:
كود:
public static int pow (int x, int n) {
     if (n==0) return 1;
 
     // find x to the n/2 recursively
     int t = pow (x, n/2);
 
     // if n is even, the result is t squared
     // if n is odd, the result is t squared times x
 
     if (n%2 == 0) {
        return t*t;
     } else {
        return t*t*x;
     }
}
مشكلة هذه الخوارزمية أنها فعالة فقط طالما أن النتيجة أصغر من 2 مليار. أعد كتابة العملية بحيث تكون النتيجة BigInteger. لكن يجب أن يبقى المعامل integer مع ذلك.
يمكنك استخدام عمليتي add وmultiply الخاصتين بالBigInteger، لكن لا تستعمل عملية pow الجاهزة، حتى لا تفسد المرح.

ملاحظة: إذا كنت مهتماً بالرسوميات، فيمكنك أن تقرأ الملحق A الآن، وأن تحل التمرينات الموجودة فيه.