سلسلة ++c للمحترفين الدرس 33: توليد الأعداد العشوائية في Cpp


محمد الميداوي

مولد قيم عشوائية حقيقيّة

لإنشاء قيم عشوائية حقّا (generate true random) يمكن استخدامها في التشفير، يجب استخدام ‎std::random_device‎ كمُولِّد.

#include <iostream>
#include <random>

int main() {
    std::random_device crypto_random_generator;
    std::uniform_int_distribution < int > int_distribution(0, 9);

 int actual_distribution[10] = {0,0,0,0,0,0,0,0,0,0}; 

    for (int i = 0; i < 10000; i++) {
        int result = int_distribution(crypto_random_generator);
        actual_distribution[result]++;
    }
    for (int i = 0; i < 10; i++) {
        std::cout << actual_distribution[i] << " ";
    }

    return 0;
}

تُستخدم std::random_device بنفس طريقة استخدام مولّد القيم العشوائية الزائفة (pseudo random value).

ورغم ذلك فيمكن تنفيذ ‎std::random_device‎ انطلاقًا من محرّك أعداد عشوائية زائفة تُحدد وفق التنفيذ في حال لم يتوفّر مصدر غير حتمي (non-deterministic) مثل جهاز خاص بتوليد القيم العشوائية لاستخدامه في التنفيذ.

يمكن الكشف عن مثل هذه التنفيذات من خلال الدالة التابعة ‎entropy‎ (التي تعيد 0 في حال كان المولد حتميًّا تمامًا)، لكنّ العديد من المكتبات الشائعة (مثل libstdc++‎ و LLVM's libc++‎) تعيد دائمًا القيمة 0، حتى عند استخدام مولّدات عشوائية خارجية عالية الجودة .

توليد عدد عشوائي زائف

تنشئ مولّدات الأعداد شبه العشوائية قيمًا يمكن تخمينها استنادًا إلى القيم التي تم توليدها سابقًا، هذا يعني أنها حتمية. ولا تستخدم مولّدات الأعداد شبه العشوائية في الحالات التي تستلزم أعدادًا عشوائية حقًّا.

#include <iostream>
#include <random>

int main() {
    std::default_random_engine pseudo_random_generator;
    std::uniform_int_distribution < int > int_distribution(0, 9);

    int actual_distribution[10] = {0,0,0,0,0,0,0,0,0,0}; 

    for (int i = 0; i < 10000; i++) {
        int result = int_distribution(pseudo_random_generator);
        actual_distribution[result]++;
    }
    for (int i = 0; i <= 9; i++) {
        std::cout << actual_distribution[i] << " ";
    }

    return 0;
}

تنشئ هذه الشيفرة مولّدَ أعدادٍ عشوائية زائفة، وتوزيعًا يولّد أعدادًا صحيحة في نطاق [0،9] باحتمال متساوي، ويحسب المولّد بعد ذلك عدد مرّات إنشاء كل نتيجة.

يحدّد معامل القالب std::uniform_int_distribution<T>‎ نوع العدد الصحيح الذي يجب إنشاؤه. استخدم ‎std::uniform_real_distribution<T>‎ لتوليد الأعداد العشرية (floats) والأعداد العشرية المزدوجة (doubles).

استخدام المولد مع عدة توزيعات

من الممكن استخدام مولّد الأعداد العشوائية مع عدة توزيعات، ويجب ذلك حقيقة.

#include <iostream>
#include <random>

int main() {
    std::default_random_engine pseudo_random_generator;
    std::uniform_int_distribution < int > int_distribution(0, 9);
    std::uniform_real_distribution < float > float_distribution(0.0, 1.0);
    std::discrete_distribution rigged_dice({1,1,1,1,1,100}); 

    std::cout << int_distribution(pseudo_random_generator) << std::endl;
    std::cout << float_distribution(pseudo_random_generator) << std::endl;
    std::cout << (rigged_dice(pseudo_random_generator) + 1) << std::endl;

    return 0;
}

عرّفنا في هذا المثال مولِّدًا واحدًا فقط، ثمّ استخدمناه لإنشاء أعداد عشوائية في ثلاثة توزيعات مختلفة، وسيولّد التوزيع ‎rigged_dice‎ قيمة بين 0 و 5، لكن سيولّد في الأغلبية الساحقة من الحالات ‎5‎، لأنّ احتمال إنشاء ‎5‎ يساوي ‎100 / 105‎.

هذا الدرس جزء من سلسلة دروس عن C++‎.

ترجمة -بتصرّف- للفصل Chapter 65: Random number generation من كتاب C++ Notes for Professionals





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن