مولد الأرقام العشوائية: كيف تُنشئ الحواسيب الأرقام العشوائية؟
الأرقام العشوائية الحقيقية: استخلاص العشوائية من الطبيعة

لننظر في طريقتين رئيسيتين تُستخدمان لتوليد الأرقام العشوائية. تعتمد الطريقة الأولى على عملية فيزيائية، وتستمد مصدر العشوائية من ظاهرة فيزيائية معينة يُتوقع أن تكون عشوائية بطبيعتها. تحدث هذه الظاهرة خارج نطاق الحاسوب، ويتم قياسها وتعديلها لأي تحيزات محتملة ناتجة عن عملية القياس نفسها. تشمل الأمثلة على هذه الظواهر الاضمحلال الإشعاعي، والتأثير الكهروضوئي، وإشعاع الخلفية الكونية، والضوضاء الجوية (التي سنستخدمها في هذا المقال)، والمزيد. وبالتالي، تُسمى الأرقام العشوائية المولدة بناءً على هذه المصادر بـ "true" random numbers أو الأرقام العشوائية الحقيقية.
من الناحية التقنية، يتكون الجزء المادي (hardware) من جهاز يحول الطاقة من شكل إلى آخر (على سبيل المثال، الإشعاع إلى إشارة كهربائية)، ومضخم (amplifier)، ومحول تناظري إلى رقمي (analog-to-digital converter) لتحويل الإخراج إلى رقم رقمي.
ما هي الأرقام شبه العشوائية؟ (Pseudorandom Numbers)

كبديل للأرقام العشوائية "true"، تتضمن الطريقة الثانية لتوليد الأرقام العشوائية خوارزميات حاسوبية يمكنها إنتاج نتائج تبدو عشوائية. لماذا تبدو عشوائية؟ لأن النتائج النهائية التي يتم الحصول عليها تتحدد بالكامل بواسطة قيمة أولية تُعرف أيضًا باسم القيمة الأولية (seed value) أو المفتاح (key). لذلك، إذا كنت تعرف قيمة المفتاح وكيف تعمل الخوارزمية، يمكنك إعادة إنتاج هذه النتائج التي تبدو عشوائية.
تُسمى مولدات الأرقام العشوائية من هذا النوع غالبًا Pseudorandom number generators (PRNGs)، ونتيجة لذلك، تُخرج أرقامًا شبه عشوائية (Pseudorandom Numbers). على الرغم من أن هذا النوع من المولدات لا يجمع عادةً أي بيانات من مصادر العشوائية الطبيعية، إلا أنه يمكن جعل جمع المفاتيح ممكنًا عند الحاجة.
دعونا نقارن بعض جوانب مولدات الأرقام العشوائية الحقيقية (TRNGs) ومولدات الأرقام شبه العشوائية (PRNGs):
- تُعد مولدات
PRNGsأسرع من مولداتTRNGs. - نظرًا لطبيعتها الحتمية (
deterministic nature)، فإنها مفيدة عندما تحتاج إلى إعادة تشغيل تسلسل من الأحداث العشوائية. وهذا يساعد كثيرًا في اختبار الشفرة البرمجية، على سبيل المثال. - من ناحية أخرى، فإن مولدات
TRNGsليست دورية (not periodic) وتعمل بشكل أفضل في الأدوار الحساسة للأمان مثل التشفير.
الدورة (period) هي عدد التكرارات التي يمر بها مولد PRNG قبل أن يبدأ في تكرار نفسه. وبالتالي، مع تساوي جميع العوامل الأخرى، فإن مولد PRNG ذو الدورة الأطول سيتطلب موارد حاسوبية أكبر للتنبؤ به واختراقه.
خوارزمية مثال لمولد الأرقام شبه العشوائية
ينفذ الحاسوب شفرة برمجية تستند إلى مجموعة من القواعد التي يجب اتباعها. بالنسبة لمولدات PRNGs بشكل عام، تدور هذه القواعد حول ما يلي:
- قبول بعض المدخلات الأولية، وهي القيمة الأولية (
seed) أو المفتاح (key). - تطبيق هذه القيمة الأولية في تسلسل من العمليات الرياضية لتوليد النتيجة.
- تكون هذه النتيجة هي الرقم العشوائي.
- استخدام الرقم العشوائي الناتج كقيمة أولية للتكرار التالي.
- تكرار العملية لمحاكاة العشوائية.
الآن دعونا نلقي نظرة على مثال.
مولد التوافق الخطي (The Linear Congruential Generator – LCG)
يُنتج هذا المولد سلسلة من الأرقام شبه العشوائية. بالنظر إلى قيمة أولية X0 ومعاملات عددية صحيحة a كمضاعف (multiplier)، و b كمُضاف (increment)، و m كمعامل القسمة (modulus)، يُعرف المولد بالعلاقة الخطية:
Xn ≡ (aXn-1 + b)mod m.
أو باستخدام صيغة أكثر ملاءمة للبرمجة:
Xn = (a * Xn-1 + b) % m.
يجب أن يفي كل من هذه الأعضاء بالشروط التالية:
m > 0(معامل القسمة موجب).0 < a < m(المضاعف موجب ولكن أقل من معامل القسمة).0 ≤ b < m(المُضاف غير سالب ولكنه أقل من معامل القسمة).0 ≤ X0< m(القيمة الأولية غير سالبة ولكنها أقل من معامل القسمة).
دعونا نُنشئ دالة JavaScript تأخذ القيم الأولية كمعاملات وتُعيد مصفوفة من الأرقام العشوائية بطول معين:
// x0=seed; a=multiplier; b=increment; m=modulus; n=desired array length;
const linearRandomGenerator = (x0, a, b, m, n) => {
const results = []
for (let i = 0; i < n; i++) {
x0 = (a * x0 + b) % m
results.push(x0)
}
return results
}
يُعد مولد التوافق الخطي (LCG) أحد أقدم وأشهر خوارزميات PRNG. أما بالنسبة لخوارزميات مولدات الأرقام العشوائية التي يمكن تنفيذها بواسطة الحواسيب، فإنها تعود إلى أربعينيات وخمسينيات القرن الماضي (مثل طريقة المربع الأوسط Middle-square method ومولد ليمر Lehmer generator) وتستمر في الكتابة حتى اليوم (مثل Xoroshiro128+ و Squares RNG والمزيد).
مثال عملي لمولد أرقام عشوائية حقيقية
عندما قررت كتابة هذا المقال حول تضمين مولد أرقام عشوائية داخل صفحة ويب، كان عليّ أن أتخذ خيارًا. كان بإمكاني استخدام دالة Math.random() في JavaScript كأساس وتوليد مخرجات بأرقام شبه عشوائية كما فعلت في مقالات سابقة (انظر Multiplication Chart - Code Your Own Times Table). لكن هذا المقال نفسه يدور حول توليد الأرقام العشوائية. لذلك قررت أن أتعلم كيفية جمع بيانات عشوائية "true" ومشاركة اكتشافي معكم.
لذا، أدناه هو مولد الأرقام العشوائية الحقيقية (True Random Number Generator). اضبط المعاملات واضغط على زر التوليد (Generate).
True Random Number Generator
Binary Decimal Hexadecimal
Result: _
تستجلب الشفرة البيانات من أحد واجهات برمجة التطبيقات (APIs)، بفضل موقع Random.org. يوفر هذا المصدر عبر الإنترنت عددًا كبيرًا من الأدوات المفيدة والقابلة للتخصيص ويأتي مع توثيق ممتاز. تأتي العشوائية من الضوضاء الجوية (atmospheric noise). لقد تمكنت من استخدام الدوال غير المتزامنة (asynchronous functions)، وهذا يمثل فائدة كبيرة للمضي قدمًا. تبدو الدالة الأساسية كما يلي:
// Generates a random number within user indicated interval
const getRandom = async (min, max, base) => {
const response = await fetch("https://www.random.org/integers/?num=1&min="+min+"&max="+max+"&col=1&base="+base+"&format=plain&rnd=new")
return response.text()
}
تسمح المعاملات التي تأخذها الدالة للمستخدم بتخصيص إخراج الرقم العشوائي. على سبيل المثال، يسمح min و max بتعيين الحدود الدنيا والعليا للمخرجات المولدة. ويحدد base ما إذا كان الإخراج يُطبع كـ binary (ثنائي)، أو decimal (عشري)، أو hexadecimal (سداسي عشري). مرة أخرى، اخترت هذا التكوين ولكن هناك العديد من الخيارات المتاحة في المصدر.
عند النقر على زر Generate، يتم استدعاء الدالة handleGenerate(). وهي بدورها تستدعي الدالة غير المتزامنة getRandom()، وتدير معالجة الأخطاء، وتُخرج النتائج:
// Output handling
const handleGenerate = () => {
handleActive(generateButton)
const base = binary.checked ? 2 : decimal.checked ? 10 : 16
if (!minimum.value || !maximum.value) {
prompter.style.color = 'red'
prompter.textContent = "Enter Min & Max values"
} else {
getRandom(minimum.value, maximum.value, base).then((data) => {
resultValue.textContent = data
prompter.textContent = ""
}).catch((error) => {
resultValue.textContent = 'ERROR'
prompter.textContent = 'Connection error. Unable to generate';
})
handleRestart()
}
}
يتعامل بقية الشفرة مع هيكل HTML والمظهر والتصميم. الشفرة جاهزة للتضمين والاستخدام داخل صفحة الويب هذه. لقد فصلتها إلى أجزاء مكونة وقدمت لها تعليقات مفصلة. يمكن تعديلها بسهولة. يمكنك أيضًا تعديل الوظائف والأنماط حسب احتياجاتك. هذا هو الرابط إلى مستودع GitHub للشفرة الكاملة: https://github.com/sandroarobeli/random-generator
الخلاصة التقنية
تُعد الأرقام العشوائية حجر الزاوية في العديد من التطبيقات الحديثة، من التشفير الآمن إلى المحاكاة العلمية واختبار البرمجيات. لقد استعرضنا في هذا المقال الفروقات الجوهرية بين الأرقام العشوائية الحقيقية التي تُستمد من ظواهر فيزيائية غير قابلة للتنبؤ، والأرقام شبه العشوائية التي تُولد بواسطة خوارزميات حتمية تعتمد على قيمة أولية (seed). لكل نوع مزاياه وعيوبه؛ فبينما توفر الأرقام الحقيقية مستوى لا مثيل له من العشوائية والأمان للتطبيقات الحساسة، تُقدم الأرقام شبه العشوائية سرعة وكفاءة وقابلية لإعادة الإنتاج، مما يجعلها مثالية لسيناريوهات مثل اختبار الشفرة البرمجية والألعاب. الفهم العميق لهذه الفروقات واختيار المولد المناسب للتطبيق المحدد هو مفتاح بناء أنظمة قوية وموثوقة.