مفهوم المضروب (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)يجب أن تُعيد1factorialize(5)يجب أن تُعيد120factorialize(10)يجب أن تُعيد3628800factorialize(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) أكثر وضوحًا وتحكمًا في تدفق التنفيذ. اختيار الطريقة الأنسب يعتمد على متطلبات الأداء، ووضوح الكود، وتفضيلات المطور. فهم هذه الأساليب المتنوعة يعزز قدرتك على حل المشكلات الخوارزمية بكفاءة ومرونة.