Генерация случайных чисел с помощью случайной библиотеки C++11
как следует из названия, я пытаюсь выяснить способ генерации случайных чисел с помощью нового C++11 <random>
библиотека. Я пробовал этот код:
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
проблема с кодом, который у меня есть, заключается в том, что каждый раз, когда я компилирую и запускаю его, он всегда генерирует одни и те же числа. Итак, мой вопрос в том, какие другие функции в случайной библиотеке могут выполнить это, будучи действительно случайными?
для моего конкретного случая использования, я пытался получить значение в пределах диапазон [1, 10]
4 ответа:
Stephan T. Lavavej (stl) из Microsoft рассказал на Going Native о том, как использовать новые случайные функции C++11 и почему бы не использовать
rand()
. В нем он включил слайд, который в основном решает ваш вопрос. Я скопировал код с этого слайда ниже.вы можете увидеть его полный разговор здесь: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"; }
мы используем:
random_device
один раз, чтобы посеять генератор случайных чисел с именемmt
.random_device()
медленнее, чемmt19937
, но его не нужно заполнять, потому что он запрашивает случайные данные из вашей операционной системы (которые будут исходить из разных мест, например RdRand например).
смотрим вопрос / ответ, явствует, что
uniform_real_distribution
возвращает число в диапазоне[a, b)
, где хочешь[a, b]
. Чтобы сделать это, нашиuniform_real_distibution
на самом деле должны выглядеть так:std::uniform_real_distribution<double> dist(1, std::nextafter(10, DBL_MAX));
моя "случайная" библиотека обеспечивает высокую удобную оболочку вокруг случайных классов C++11. Вы можете сделать почти все вещи с помощью простого метода "get".
примеры:
случайное число в диапазоне
auto val = Random::get(-10, 10); // Integer auto val = Random::get(10.f, -10.f); // Float point
случайных булевых
auto val = Random::get<bool>( ) // 50% to generate true auto val = Random::get<bool>( 0.7 ) // 70% to generate true
случайное значение из std:: initilizer_list
auto val = Random::get( { 1, 3, 5, 7, 9 } ); // val = 1 or 3 or...
случайный итератор из диапазона итератора или все контейнер
auto it = Random::get( vec.begin(), vec.end() ); // it = random iterator auto it = Random::get( vec ); // return random iterator
и даже больше вещей ! Проверьте страницу github:
вот что я только что написал по этим строкам::
#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; }
~
у вас есть две типичные ситуации. Во-первых, вы хотите случайные числа и не слишком беспокоитесь о качестве или скорости выполнения. В этом случае используйте следующий макрос
#define uniform() (rand()/(RAND_MAX + 1.0))
это дает вам p в диапазоне от 0 до 1 - Эпсилон (если RAND_MAX не больше, чем точность двойника, но беспокоиться об этом, когда вы приходите к нему).
int x = (int) (uniform() * N);
теперь дает случайное целое число от 0 до N -1.
Если вам нужно другие дистрибутивы, вы должны превратить стр. Или иногда проще назвать равномерным() несколько раз.
Если вы хотите повторяемое поведение, семя с константой, в противном случае семя с вызовом time().
теперь, если вас беспокоит качество или производительность во время выполнения, перепишите uniform(). Но в противном случае не трогайте код. Всегда сохраняйте равномерность() от 0 до 1 минус Эпсилон. Теперь вы можете обернуть библиотеку случайных чисел C++, чтобы создать лучшую униформу(), но это своего рода вариант среднего уровня. Если вас беспокоят характеристики ГСЧ, то также стоит потратить немного времени, чтобы понять, как работают основные методы, а затем предоставить один. Таким образом, у вас есть полный контроль над кодом, и вы можете гарантировать, что с одним и тем же семенем последовательность всегда будет точно такой же, независимо от платформы или версии C++, на которую вы ссылаетесь.