Generowanie liczb losowych przy użyciu biblioteki losowej C++11
Jak sugeruje tytuł, staram się wymyślić sposób generowania liczb losowych za pomocą nowej biblioteki C++11 <random>
. Próbowałem z tym kodem:
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
Problem z kodem, który mam polega na tym, że za każdym razem, gdy go kompiluję i uruchamiam, zawsze generuje te same liczby. Więc moje pytanie brzmi, jakie inne funkcje w random library mogą to osiągnąć, będąc naprawdę losowym?
Dla mojego konkretnego przypadku użycia, próbowałem uzyskać wartość w zakresie [1, 10]
4 answers
[[11]}Stephan T. Lavavej (stl) z Microsoft wygłosił wykład na Going Native o tym, jak używać nowych funkcji losowych C++11 i dlaczego nie używać rand()
. W nim zawarł slajd, który zasadniczo rozwiązuje Twoje pytanie. Skopiowałem kod z poniższego slajdu.
#include <random>
#include <iostream>
int main() {
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_real_distribution<double> dist(1.0, 10.0);
for (int i=0; i<16; ++i)
std::cout << dist(mt) << "\n";
}
Używamy random_device
raz do zalania generatora liczb losowych o nazwie mt
. random_device()
jest wolniejszy niż mt19937
, ale nie musi być seeded, ponieważ żąda losowych danych z twojego systemu operacyjnego(które będą źródłem z różnych lokalizacji, na przykład RdRand).
Patrząc na to pytanie / odpowiedź , wydaje się, że uniform_real_distribution
Zwraca liczbę z zakresu [a, b)
, gdzie chcesz [a, b]
. Aby to zrobić, nasza {[10] } powinna wyglądać tak:
std::uniform_real_distribution<double> dist(1, std::nextafter(10, DBL_MAX));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:06
Moja 'losowa' biblioteka zapewnia wygodną owijkę wokół losowych klas C++11. Możesz zrobić prawie wszystkie rzeczy za pomocą prostej metody "get".
Przykłady:
-
Liczba losowa w przedziale
auto val = Random::get(-10, 10); // Integer auto val = Random::get(10.f, -10.f); // Float point
-
Random boolean
auto val = Random::get<bool>( ) // 50% to generate true auto val = Random::get<bool>( 0.7 ) // 70% to generate true
-
Losowa wartość z std::initilizer_list
auto val = Random::get( { 1, 3, 5, 7, 9 } ); // val = 1 or 3 or...
-
Losowy iterator z zakresu iteratora lub cały kontener
auto it = Random::get( vec.begin(), vec.end() ); // it = random iterator auto it = Random::get( vec ); // return random iterator
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-07 18:57:37
Oto coś, co właśnie napisałem::
#include <random>
#include <chrono>
#include <thread>
using namespace std;
//==============================================================
// RANDOM BACKOFF TIME
//==============================================================
class backoff_time_t {
public:
random_device rd;
mt19937 mt;
uniform_real_distribution<double> dist;
backoff_time_t() : rd{}, mt{rd()}, dist{0.5, 1.5} {}
double rand() {
return dist(mt);
}
};
thread_local backoff_time_t backoff_time;
int main(int argc, char** argv) {
double x1 = backoff_time.rand();
double x2 = backoff_time.rand();
double x3 = backoff_time.rand();
double x4 = backoff_time.rand();
return 0;
}
~
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-21 02:44:02
Masz dwie typowe sytuacje. Pierwszy polega na tym, że chcesz losowych liczb i nie jesteś zbyt zaniepokojony jakością lub szybkością wykonania. W takim przypadku użyj następującego makra
#define uniform() (rand()/(RAND_MAX + 1.0))
To daje p w zakresie od 0 do 1-epsilon (chyba, że RAND_MAX jest większy niż precyzja podwójnego, ale martw się o to, gdy do tego dojdzie).
Int x = (int) (uniform () * N);
Teraz daje losową liczbę całkowitą na 0 do n -1.
Jeśli potrzebujesz innych dystrybucji, musisz przekształć p. lub czasami łatwiej jest kilkukrotnie wywołać uniform ().
Jeśli chcesz powtarzalnego zachowania, seed ze stałą, w przeciwnym razie seed z wywołaniem do time ().
Teraz, jeśli martwisz się o jakość lub wydajność czasu pracy, zmień metodę uniform (). Ale poza tym nie dotykaj kodu. Zawsze trzymaj uniform () na 0 do 1 minus epsilon. Teraz możesz owinąć bibliotekę liczb losowych C++, aby utworzyć lepszą uniform (), ale jest to rodzaj opcji średniego poziomu. Jeśli jesteś zaniepokojony cechy RNG, to warto również zainwestować trochę czasu, aby zrozumieć, jak działają podstawowe metody, a następnie zapewnić jeden. Masz więc pełną kontrolę nad kodem i możesz zagwarantować, że przy tym samym zalążku sekwencja będzie zawsze taka sama, niezależnie od platformy lub wersji C++, z którą linkujesz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-10 12:37:16