Я перемальовував усі речі вище, приблизно 40 інших сторінок із c ++, як це, і переглядав відео Стефана Т. Лававея "STL"
і досі не був впевнений, як випадкові числа працюють у практиці, тому я взяв повну неділю, щоб зрозуміти про що це все і як це працює і чи можна використовувати.
На мій погляд, STL має рацію щодо того, що "більше не використовуйте сранд", і він це добре пояснив у відео 2 . Він також рекомендує використовувати:
а) void random_device_uniform()
- для зашифрованого генерування, але повільніше (з мого прикладу)
б) приклади з mt19937
- швидше, здатність створювати насіння, не зашифровані
Я витягнув усі заявлені на с ++ 11 книг, до яких я маю доступ, і виявив, що німецькі автори, такі як Breymann (2015), все ще використовують клон
srand( time( 0 ) );
srand( static_cast<unsigned int>(time(nullptr))); or
srand( static_cast<unsigned int>(time(NULL))); or
просто <random>
замість<time> and <cstdlib>
включень - тому будьте обережні, щоб дізнатися лише з однієї книги :).
Значення - його не слід використовувати з c ++ 11, оскільки:
Програми часто потребують джерела випадкових чисел. До нового стандарту і C, і C ++ покладалися на просту функцію C бібліотеки з назвою rand. Ця функція створює псевдовипадкові цілі числа, які рівномірно розподілені в діапазоні від 0 до максимального значення, що залежить від системи, що становить принаймні 32767. Функція rand має кілька проблем: багатьом, якщо не більшості, програмам потрібні випадкові числа в іншому діапазоні від той, який виробляється rand. Деякі програми вимагають випадкових чисел з плаваючою комою. Деяким програмам потрібні номери, які відображають неоднорідний розподіл. Програмісти часто вводять не випадковість, коли намагаються перетворити діапазон, тип або розподіл чисел, породжених rand. (цитата з Lippmans C ++ грунтовки п'ятого видання 2012)
Нарешті, я знайшов найкраще пояснення з 20 книг у «Біярн Структурпс» новіших - і він повинен знати свої речі - у «Подорожі C ++ 2019», «Принципи програмування та практики використання C ++ 2016» та «Мова програмування C ++ 4-е видання 2014 ", а також кілька прикладів у" Lippmans C ++ грунтовці п'ятого видання 2012 ":
І це дуже просто, тому що генератор випадкових чисел складається з двох частин:
(1) двигун, який виробляє послідовність випадкових чи псевдовипадкових значень. (2) розподіл, який відображає ці значення в математичний розподіл у діапазоні.
Незважаючи на думку хлопця Microsofts STL, Bjarne Stroustrups пише:
У стандартній бібліотеці передбачені двигуни та розподіли випадкових чисел (§24.7). За замовчуванням використовуйте default_random_engine, який вибирається для широкого застосування та низької вартості.
void die_roll()
Приклад від Бьярн Stroustrups - хороша ідея генерації двигун і розподіл з using
(більш боєм , що тут) .
Щоб мати можливість практично використовувати генератори випадкових чисел, що надаються стандартною бібліотекою, <random>
тут є якийсь виконуваний код із різними прикладами, зведеним до найменш необхідного, що, сподіваємось, безпечний час та гроші для вас, хлопці:
#include <random> //random engine, random distribution
#include <iostream> //cout
#include <functional> //to use bind
using namespace std;
void space() //for visibility reasons if you execute the stuff
{
cout << "\n" << endl;
for (int i = 0; i < 20; ++i)
cout << "###";
cout << "\n" << endl;
}
void uniform_default()
{
// uniformly distributed from 0 to 6 inclusive
uniform_int_distribution<size_t> u (0, 6);
default_random_engine e; // generates unsigned random integers
for (size_t i = 0; i < 10; ++i)
// u uses e as a source of numbers
// each call returns a uniformly distributed value in the specified range
cout << u(e) << " ";
}
void random_device_uniform()
{
space();
cout << "random device & uniform_int_distribution" << endl;
random_device engn;
uniform_int_distribution<size_t> dist(1, 6);
for (int i=0; i<10; ++i)
cout << dist(engn) << ' ';
}
void die_roll()
{
space();
cout << "default_random_engine and Uniform_int_distribution" << endl;
using my_engine = default_random_engine;
using my_distribution = uniform_int_distribution<size_t>;
my_engine rd {};
my_distribution one_to_six {1, 6};
auto die = bind(one_to_six,rd); // the default engine for (int i = 0; i<10; ++i)
for (int i = 0; i <10; ++i)
cout << die() << ' ';
}
void uniform_default_int()
{
space();
cout << "uniform default int" << endl;
default_random_engine engn;
uniform_int_distribution<size_t> dist(1, 6);
for (int i = 0; i<10; ++i)
cout << dist(engn) << ' ';
}
void mersenne_twister_engine_seed()
{
space();
cout << "mersenne twister engine with seed 1234" << endl;
//mt19937 dist (1234); //for 32 bit systems
mt19937_64 dist (1234); //for 64 bit systems
for (int i = 0; i<10; ++i)
cout << dist() << ' ';
}
void random_seed_mt19937_2()
{
space();
cout << "mersenne twister split up in two with seed 1234" << endl;
mt19937 dist(1234);
mt19937 engn(dist);
for (int i = 0; i < 10; ++i)
cout << dist() << ' ';
cout << endl;
for (int j = 0; j < 10; ++j)
cout << engn() << ' ';
}
int main()
{
uniform_default();
random_device_uniform();
die_roll();
random_device_uniform();
mersenne_twister_engine_seed();
random_seed_mt19937_2();
return 0;
}
Я думаю, що це все додає, і, як я вже сказав, мені знадобилося чимало читання та час, щоб перерахувати це на приклади - якщо у вас є додаткові відомості про генерацію чисел, я радий дізнатися про це через вечір або в розділі коментарів і додасть її за потреби або відредагує цю публікацію. Бул