ثلاث طرق فعّالة لحساب مضروب عدد في JavaScript

دقائق القراءة: 6

مفهوم المضروب (Factorial) لعدد صحيح غير سالب n في الرياضيات قد يبدو تحديًا خوارزميًا للمبتدئين. في هذا المقال، سأستعرض ثلاث طرق فعّالة لحساب مضروب عدد في JavaScript: الأولى باستخدام الدالة التراجعية (recursive function)، والثانية باستخدام حلقة while loop، والثالثة باستخدام حلقة for loop.

تحدي الخوارزمية: حساب المضروب

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

على سبيل المثال:

5! = 1 * 2 * 3 * 4 * 5 = 120

إليك الدالة الأساسية التي سنعمل عليها:

function factorialize(num) {
  return num;
}
factorialize(5);

حالات الاختبار المُقدمة:

  • factorialize(0) يجب أن تُعيد 1
  • factorialize(5) يجب أن تُعيد 120
  • factorialize(10) يجب أن تُعيد 3628800
  • factorialize(20) يجب أن تُعيد 2432902008176640000

ما هو مضروب العدد؟

عند حساب مضروب عدد، فإنك تضرب هذا العدد في كل عدد متتالٍ يقل عنه بواحد حتى تصل إلى 1. إذا كان العدد 5، فستحصل على:

5! = 5 * 4 * 3 * 2 * 1

النمط العام للمضروب هو كما يلي:

0! = 1
1! = 1
2! = 2 * 1
3! = 3 * 2 * 1
4! = 4 * 3 * 2 * 1
5! = 5 * 4 * 3 * 2 * 1

1. حساب المضروب باستخدام الدوال التراجعية (Recursion)

تعتمد الدوال التراجعية على استدعاء الدالة لنفسها بشكل متكرر حتى يتم الوصول إلى شرط توقف معين. في حالة المضروب، يكون شرط التوقف هو عندما يصبح العدد 0 أو أقل.

function factorialize(num) {
  // إذا كان الرقم أقل من 0، نرفضه.
  if (num < 0) return -1;
  // إذا كان الرقم 0، فمضروبه هو 1.
  else if (num == 0) return 1;
  // وإلا، استدعِ الإجراء التراجعي مرة أخرى.
  else {
    return (num * factorialize(num - 1));
    /* الجزء الأول من طريقة التراجع
    يجب أن تتذكر أنه لن يكون لديك استدعاء واحد فقط، بل عدة استدعاءات متداخلة.
    كل استدعاء: num === "?"
    num * factorialize(num - 1)
    الاستدعاء الأول – factorialize(5) سيعيد 5 * factorialize(5 - 1) // factorialize(4)
    الاستدعاء الثاني – factorialize(4) سيعيد 4 * factorialize(4 - 1) // factorialize(3)
    الاستدعاء الثالث – factorialize(3) سيعيد 3 * factorialize(3 - 1) // factorialize(2)
    الاستدعاء الرابع – factorialize(2) سيعيد 2 * factorialize(2 - 1) // factorialize(1)
    الاستدعاء الخامس – factorialize(1) سيعيد 1 * factorialize(1 - 1) // factorialize(0)

    الجزء الثاني من طريقة التراجع
    تصل الدالة إلى شرط if، وتُعيد 1 الذي سيُضرب في num
    ستخرج الدالة بالقيمة الإجمالية
    الاستدعاء الخامس سيعيد (5 * (5 - 1)) // num = 5 * 4
    الاستدعاء الرابع سيعيد (20 * (4 - 1)) // num = 20 * 3
    الاستدعاء الثالث سيعيد (60 * (3 - 1)) // num = 60 * 2
    الاستدعاء الثاني سيعيد (120 * (2 - 1)) // num = 120 * 1
    الاستدعاء الأول سيعيد (120) // num = 120
    إذا جمعنا كل الاستدعاءات في سطر واحد، نحصل على
    (5 * (5 - 1) * (4 - 1) * (3 - 1) * (2 - 1)) = 5 * 4 * 3 * 2 * 1 = 120
    */
  }
}
factorialize(5);

نسخة بدون تعليقات:

function factorialize(num) {
  if (num < 0) return -1;
  else if (num == 0) return 1;
  else {
    return (num * factorialize(num - 1));
  }
}
factorialize(5);

2. حساب المضروب باستخدام حلقة WHILE

تُعد حلقة while طريقة أخرى لحساب المضروب، حيث تستمر في التكرار طالما أن الشرط المحدد صحيح. هنا، نستمر في الضرب طالما أن العدد أكبر من 1.

function factorialize(num) {
  // الخطوة 1. أنشئ متغيرًا result لتخزين num
  var result = num;
  // إذا كان num = 0 أو num = 1، سيعيد المضروب 1
  if (num === 0 || num === 1) return 1;
  // الخطوة 2. أنشئ حلقة WHILE
  while (num > 1) {
    num--; // إنقاص بـ 1 في كل تكرار
    result = result * num; // أو result *= num;
    /*
    num   num--   var result   result *= num
    التكرار الأول: 5     4       5            20 = 5 * 4
    التكرار الثاني: 4     3       20           60 = 20 * 3
    التكرار الثالث: 3     2       60           120 = 60 * 2
    التكرار الرابع: 2     1       120          120 = 120 * 1
    التكرار الخامس: 1     0       120          نهاية حلقة WHILE
    */
  }
  // الخطوة 3. أعد مضروب العدد الصحيح المُعطى
  return result; // 120
}
factorialize(5);

نسخة بدون تعليقات:

function factorialize(num) {
  var result = num;
  if (num === 0 || num === 1) return 1;
  while (num > 1) {
    num--;
    result *= num;
  }
  return result;
}
factorialize(5);

3. حساب المضروب باستخدام حلقة FOR

تُقدم حلقة for طريقة منظمة لتكرار عملية الضرب. نبدأ من num - 1 ونستمر في الضرب حتى نصل إلى 1.

function factorialize(num) {
  // إذا كان num = 0 أو num = 1، سيعيد المضروب 1
  if (num === 0 || num === 1) return 1;
  // نبدأ حلقة FOR من i = num - 1
  // ننقص i بعد كل تكرار
  for (var i = num - 1; i >= 1; i--) {
    // نخزن قيمة num في كل تكرار
    num = num * i; // أو num *= i;
    /*
    num   var i = num - 1   num *= i   i--   i >= 1?
    التكرار الأول: 5     4 = 5 - 1       20 = 5 * 4   3     نعم
    التكرار الثاني: 20    3 = 4 - 1       60 = 20 * 3  2     نعم
    التكرار الثالث: 60    2 = 3 - 1       120 = 60 * 2 1     نعم
    التكرار الرابع: 120   1 = 2 - 1       120 = 120 * 1 0     لا
    التكرار الخامس: 120   0               120          نهاية حلقة FOR
    */
  }
  return num; // 120
}
factorialize(5);

نسخة بدون تعليقات:

function factorialize(num) {
  if (num === 0 || num === 1) return 1;
  for (var i = num - 1; i >= 1; i--) {
    num *= i;
  }
  return num;
}
factorialize(5);

💡 الخلاصة التقنية

لقد استعرضنا في هذا المقال ثلاث استراتيجيات رئيسية لحساب مضروب عدد في JavaScript: النهج التراجعي (recursion) الذي يوفر حلاً أنيقًا ومختصرًا ولكنه قد يستهلك موارد أكثر في حالات الأعداد الكبيرة، وحلقتا while و for اللتان تُقدمان حلولًا تكرارية (iterative) أكثر وضوحًا وتحكمًا في تدفق التنفيذ. اختيار الطريقة الأنسب يعتمد على متطلبات الأداء، ووضوح الكود، وتفضيلات المطور. فهم هذه الأساليب المتنوعة يعزز قدرتك على حل المشكلات الخوارزمية بكفاءة ومرونة.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *