Podpisałem wszystkie powyższe rzeczy, około 40 innych stron z c ++ w ten sposób i obejrzałem wideo Stephana T. Lavaveja "STL"
i nadal nie byłem pewien, jak liczby losowe działają w praktyce, więc poświęciłem całą niedzielę, aby się dowiedzieć o co w tym wszystkim chodzi i jak to działa i może być używane.
Moim zdaniem STL ma rację co do „nieużywania już srand” i wyjaśnił to dobrze w wideo 2 . Zaleca również użycie:
a) void random_device_uniform()
- dla zaszyfrowanego generowania, ale wolniej (z mojego przykładu)
b) przykłady z mt19937
- szybszym, możliwością tworzenia seedów, nie jest szyfrowane
Wyciągnąłem wszystkie zgłoszone książki C ++ 11, do których mam dostęp, i stwierdziłem, że niemieccy autorzy, tacy jak Breymann (2015), nadal używają klonu
srand( time( 0 ) );
srand( static_cast<unsigned int>(time(nullptr))); or
srand( static_cast<unsigned int>(time(NULL))); or
tylko z <random>
zamiast <time> and <cstdlib>
#includings - więc uważaj, aby uczyć się tylko z jednej książki :).
Znaczenie - tego nie należy używać od czasu C ++ 11, ponieważ:
Programy często potrzebują źródła liczb losowych. Przed nowym standardem zarówno C, jak i C ++ korzystały z prostej funkcji biblioteki C o nazwie rand. Ta funkcja tworzy pseudolosowe liczby całkowite, które są równomiernie rozłożone w zakresie od 0 do zależnej od systemu wartości maksymalnej wynoszącej co najmniej 32767. Funkcja rand ma kilka problemów: Wiele programów, jeśli nie większość, potrzebuje liczb losowych z innego zakresu niż jeden wyprodukowany przez rand. Niektóre aplikacje wymagają losowych liczb zmiennoprzecinkowych. Niektóre programy wymagają liczb, które odzwierciedlają niejednorodną dystrybucję. Programiści często wprowadzają nielosowość, gdy próbują przekształcić zakres, typ lub rozkład liczb generowanych przez rand. (cytat z Lippmans C ++ primer piąta edycja 2012)
W końcu znalazłem najlepsze wyjaśnienie z 20 nowszych książek Bjarne Stroustrupsa - a on powinien znać się na swoich rzeczach - w „Wycieczka po C ++ 2019”, „Zasady programowania i praktyka przy użyciu C ++ 2016” oraz „Język programowania C ++, wydanie 4 2014 ”, a także kilka przykładów w„ Lippmans C ++ primer piąta edycja 2012 ”:
Jest to naprawdę proste, ponieważ generator liczb losowych składa się z dwóch części:
(1) silnika, który tworzy sekwencję wartości losowych lub pseudolosowych. (2) rozkład, który odwzorowuje te wartości w matematycznym rozkładzie w zakresie.
Wbrew opinii gościa z Microsoftu STL, Bjarne Stroustrups pisze:
W programie biblioteka standardowa zapewnia silniki liczb losowych i dystrybucje (§24.7). Domyślnie użyj default_random_engine, który jest wybrany ze względu na szerokie zastosowanie i niski koszt.
void die_roll()
Przykład pochodzi z Bjarne Stroustrups - dobry pomysł silnik generowania i dystrybucji z using
(bardziej że walka tutaj) .
Aby móc w praktyce skorzystać z generatorów liczb losowych dostarczonych przez bibliotekę standardową, <random>
tutaj trochę kodu wykonywalnego z różnymi przykładami zredukowanymi do najmniej potrzebnego, który, miejmy nadzieję, pozwoli wam zaoszczędzić czas i pieniądze:
#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;
}
Myślę, że to wszystko sumuje i tak jak powiedziałem, zajęło mi sporo czytania i czasu, aby odłożyć to do tych przykładów - jeśli masz więcej rzeczy na temat generowania liczb, cieszę się, że o tym usłyszę po południu lub w sekcji komentarzy i doda go w razie potrzeby lub edytuje ten post. Bool