ما معنى PRNG (مولّد الأعداد العشوائية الزائفة)؟ شرح مبسّط مع أمثلة
اختصار PRNG يعني «مولّد الأعداد العشوائية الزائفة» (Pseudo-Random Number Generator)، وهو خوارزمية تُنتج سلسلة من الأرقام تبدو عشوائية لكنها في الحقيقة محسوبة بالكامل. أما عبارة «see pseudo-random number generator» التي قد تراها ملتصقة بالاختصار، فهي ليست جزءًا من المصطلح؛ إنها مجرد إحالة في قاموس تقني تعني حرفيًا «انظر إلى مدخل: مولّد الأعداد العشوائية الزائفة». بمعنى آخر، الكلمة الحقيقية هي PRNG فقط، والباقي مرجع للفهرسة انتقل بالخطأ إلى العنوان.
لماذا تُسمّى «زائفة»؟
الوصف «زائفة» (Pseudo) دقيق جدًا وليس انتقاصًا. الحاسوب جهاز حتمي: إذا أعطيته المدخلات نفسها أعطاك النتيجة نفسها في كل مرة، لذلك لا يستطيع من تلقاء نفسه إنتاج عشوائية حقيقية. ما يفعله المولّد أنه يبدأ من قيمة أولية تُسمّى البذرة (Seed)، ثم يطبّق عليها معادلة رياضية بشكل متكرر، فتخرج أرقام تتوزع توزيعًا يشبه العشوائية الإحصائية، مع أنها متتابعة ومحدَّدة سلفًا.
النتيجة المهمة عمليًا: البذرة نفسها تُنتج التسلسل نفسه دائمًا. هذه ليست عيبًا، بل ميزة تُستغل كثيرًا في البرمجة، كما سنرى.
كيف يعمل المولّد فعليًا؟
أبسط مثال كلاسيكي هو المولّد الخطي التوافقي (Linear Congruential Generator)، الذي يحسب كل رقم من سابقه بمعادلة واحدة:
X(next) = ( a × X(current) + c ) mod m
حيث a وc وm ثوابت مختارة بعناية، وX القيمة الحالية التي تبدأ من البذرة. كل خطوة تأخذ الرقم السابق وتُخرج رقمًا جديدًا ضمن المدى، وهكذا تتولد السلسلة. المولّدات الحديثة مثل Mersenne Twister أعقد بكثير وتُنتج أرقامًا ذات جودة إحصائية عالية جدًا وفترة تكرار هائلة، لكن الفكرة الجوهرية واحدة: معادلة + حالة داخلية + بذرة.
نقطة يخطئ فيها المبتدئون كثيرًا: إذا لم تُغيّر البذرة، حصلت على الأرقام «العشوائية» نفسها في كل تشغيل. لهذا تُشتق البذرة عادةً من مصدر متغيّر مثل توقيت النظام باللحظة (time) عند بدء البرنامج.
أين يُستخدم PRNG؟
- المحاكاة والنمذجة: تجارب مونت كارلو، محاكاة الفيزياء، نماذج الأرصاد، حيث نحتاج ملايين الأرقام بسرعة.
- الألعاب: توزيع الورق، حركة الأعداء، الغنائم العشوائية.
- الخوارزميات: مثل اختيار محور عشوائي في «الفرز السريع» لتفادي أسوأ الحالات، وخوارزميات التجزئة (Hashing).
- الاختبار: توليد بيانات اختبار عشوائية قابلة لإعادة الإنتاج عند تثبيت البذرة، فتستطيع تكرار الخطأ نفسه بالضبط أثناء التصحيح.
PRNG أم المولّد العشوائي الحقيقي (TRNG)؟
كثيرون يخلطون بين النوعين. الفرق جوهري:
| المعيار | مولّد زائف (PRNG) | مولّد حقيقي (TRNG) |
|---|---|---|
| مصدر العشوائية | معادلة رياضية + بذرة | ظاهرة فيزيائية (ضجيج حراري، تحلل إشعاعي) |
| القابلية للتكرار | نعم، بنفس البذرة | لا، غير قابل للتكرار |
| السرعة | عالية جدًا | أبطأ عادةً |
| يحتاج عتادًا خاصًا | لا | غالبًا نعم |
| الاستخدام النموذجي | محاكاة، ألعاب، اختبار | توليد مفاتيح تشفير، بذور آمنة |
الخلاصة: PRNG سريع وعملي لأغلب الاستخدامات، لكن التكرار الذي يميّزه يصبح خطرًا حين يتعلق الأمر بالأمان.
تحذير مهم: لا تستخدم PRNG العادي في التشفير
هذا أشهر خطأ أمني في المجال. دالة مثل rand() في لغة C أو Math.random() في جافاسكربت هي مولّد زائف عادي، ويمكن للمهاجم — إذا عرف جزءًا من المخرجات — أن يستنتج الحالة الداخلية ويتنبأ بكل الأرقام القادمة. لذلك لا يجوز أبدًا توليد كلمات مرور أو مفاتيح تشفير أو رموز جلسات بهذه الدوال.
للأغراض الأمنية يوجد نوع مخصّص اسمه CSPRNG (المولّد الزائف الآمن تشفيريًا)، وهو مصمَّم بحيث يستحيل عمليًا التنبؤ بمخرجاته حتى مع معرفة جزء منها. استعمل الدوال المخصصة لذلك، مثل secrets في بايثون، أو crypto.randomBytes في Node.js، أو /dev/urandom في أنظمة لينكس.
الأسئلة الشائعة
هل الأرقام الناتجة عن PRNG عشوائية فعلًا؟ لا، إنها حتمية بالكامل ومحسوبة من البذرة، لكنها تجتاز اختبارات إحصائية للعشوائية، وهذا يكفي لأغلب التطبيقات غير الأمنية.
ما البذرة (Seed) ولماذا تهمّني؟ هي القيمة الأولية التي ينطلق منها المولّد. تثبيتها يجعل النتائج قابلة للتكرار (مفيد للاختبار)، وتغييرها عند كل تشغيل يجعل السلسلة تبدو جديدة في كل مرة.
ماذا تعني «see pseudo-random number generator» في العنوان؟ لا شيء تقني؛ إنها إحالة قاموسية تعني «راجع مدخل مولّد الأعداد العشوائية الزائفة». المصطلح المقصود هو PRNG فقط.
هل يمكنني استخدام Math.random() لتوليد كلمة مرور؟
لا، فهي غير آمنة وقابلة للتنبؤ. استخدم مولّدًا آمنًا تشفيريًا مثل crypto.randomBytes أو مكتبة secrets.