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]

Author: smac89, 2013-10-29

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.

[[11]}możesz zobaczyć jego pełną wypowiedź tutaj: http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
#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));
 151
Author: Bill Lynch,
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:

  1. Liczba losowa w przedziale

    auto val = Random::get(-10, 10); // Integer
    auto val = Random::get(10.f, -10.f); // Float point
    
  2. Random boolean

    auto val = Random::get<bool>( ) // 50% to generate true
    auto val = Random::get<bool>( 0.7 ) // 70% to generate true
    
  3. Losowa wartość z std::initilizer_list

    auto val = Random::get( { 1, 3, 5, 7, 9 } ); // val = 1 or 3 or...
    
  4. 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
    
I jeszcze więcej ! Sprawdź github Strona:

Https://github.com/effolkronium/random

 15
Author: Ilya Polishchuk,
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;
}

~

 2
Author: Bill Moore,
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.

 -2
Author: Malcolm McLean,
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