Как следует из названия, я пытаюсь найти способ генерирования случайных чисел с помощью новой библиотеки С++ 11 <random>
. Я пробовал это с этим кодом:
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
Проблема с кодом, который у меня есть, состоит в том, что каждый раз, когда я компилирую и запускаю его, он всегда генерирует одинаковые числа. Итак, мой вопрос: какие другие функции в случайной библиотеке могут выполнить это, будучи действительно случайным?
Для моего конкретного случая использования я пытался получить значение в диапазоне [1, 10]
Ответ 1
Стефан Т. Лававей (stl) из Microsoft выступил с докладом в Going Native о том, как использовать новые случайные функции С++ 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
один раз для random_device
генератора случайных чисел с именем mt
. random_device()
медленнее, чем mt19937
, но его не нужно mt19937
, потому что он запрашивает случайные данные из вашей операционной системы (которая будет получать данные из разных мест, например, RdRand).
Глядя на этот вопрос/ответ, кажется, uniform_real_distribution
возвращает число в диапазоне [a, b)
, где вы хотите [a, b]
. Чтобы сделать это, uniform_real_distibution
должен выглядеть так:
std::uniform_real_distribution<double> dist(1, std::nextafter(10, DBL_MAX));
Ответ 2
Моя "случайная" библиотека обеспечивает удобную оболочку вокруг случайных классов С++ 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:
https://github.com/effolkronium/random
Ответ 3
Здесь что-то, что я написал только по этим строкам::
#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;
}
~
Ответ 4
Вот некоторый ресурс, который вы можете прочитать о генераторе псевдослучайных чисел.
https://en.wikipedia.org/wiki/Pseudorandom_number_generator
Как правило, случайные числа в компьютере требуют начального числа (это число может быть текущим системным временем).
замещать
std::default_random_engine generator;
От
std::default_random_engine generator(<some seed number>);
Ответ 5
У вас две распространенные ситуации. Во-первых, вы хотите получить случайные числа и не слишком суетиться о качестве или скорости выполнения. В этом случае используйте следующий макрос
#define uniform() (rand()/(RAND_MAX + 1.0))
который дает вам значение p в диапазоне от 0 до 1 - epsilon (если только RAND_MAX больше, чем точность двойника, но беспокоиться об этом, когда вы приходите к нему).
int x = (int) (равномерное() * N);
Теперь дает случайное целое число от 0 до N -1.
Если вам нужны другие дистрибутивы, вам нужно преобразовать p. Или иногда проще называть uniform() несколько раз.
Если вы хотите повторяемое поведение, семя с константой, иначе семя с вызовом time().
Теперь, если вы обеспокоены качеством или временем выполнения, перепишите форму(). Но в остальном не трогайте код. Всегда сохраняйте равномерное() на 0-1 минус эпсилон. Теперь вы можете обернуть библиотеку случайных чисел С++, чтобы создать лучшую форму(), но это своего рода вариант среднего уровня. Если вас беспокоят характеристики RNG, то также стоит потратить немного времени, чтобы понять, как работают лежащие в основе методы, а затем предоставить их. Таким образом, у вас есть полный контроль над кодом, и вы можете гарантировать, что с тем же самым семенем последовательность всегда будет точно такой же, независимо от платформы или версии С++, на которую вы ссылаетесь.