генерировать случайное число в с ++ - PullRequest
0 голосов
/ 14 декабря 2018

Я получил задачу генерировать десятки тысяч случайных чисел в c ++.Я много гуглил о случайных числах в c ++ и искал ссылку на c ++, но сейчас запутался.

Как я знаю, random_device - это недетерминированный генератор случайных чисел, но каждый раз, когда язапустить мою программу, случайное число, генерируемое random_device, то же самое.Итак, как мне установить начальное значение для random_device, чтобы случайное число отличалось при перезапуске моей программы?

И я прочитал, что в std :: random_device может закончиться энтропия, если вы попытаетесь получитьмного цифр от него. Это может привести к его блокировке, пока вы не двигаете мышь или что-то ».Это означает, что моя программа может остановиться в какое-то время.Как я могу избежать этого?

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Если вам не требуется криптографически безопасное генерирование случайных чисел, тогда вы можете использовать генератор случайных чисел std::mt19937.Это генератор случайных чисел Meresenne Twister , который имеет период 2 19937 итераций перед повторением.Я использовал это в прошлом:

std::array<int, std::mt19937::state_size> seedData;
std::random_device  randDevice;
std::mt19937 eng;
std::uniform_real_distribution<double> randGen(0, 1);
std::generate_n(seedData.data(), seedData.size(), std::ref(randDevice));
std::seed_seq seq(std::begin(seedData), std::end(seedData));
eng.seed(seq);

Это создает массив, содержащий начальное число соответствующего размера.Создает случайное устройство для настройки семян.Затем создается генератор случайных чисел mt19937 для генерации чисел.Чтобы использовать его для генерации значений от 0 до 1, вы можете использовать std::uniform_real_distribution следующим образом:

double randVal = randGen(eng);
0 голосов
/ 14 декабря 2018

Начиная с здесь , вы можете видеть, что std::random_device не всегда гарантирует недетерминированность:

std :: random_device может быть реализовано в терминах реализации-определенный механизм псевдослучайных чисел , если недетерминированный источник (например, аппаратное устройство) недоступен для реализации.В этом случае каждый объект std :: random_device может генерировать одинаковую числовую последовательность .

В Linux он по умолчанию использует /dev/urandom или RDRND инструкцию ЦП согласно здесь :

Реализации в libc ++ и libstdc ++ предполагают, что токен будет именем символьного устройства, которое при чтении выдает случайные числа со значением по умолчанию "/ dev/ urandom ", хотя там, где доступна инструкция процессора RDRND, libstdc ++ использует ее по умолчанию .

, которая не будет блокировать .Вы можете переключиться на даже защищенное устройство /dev/random, используя подход здесь , но это устройство будет блокироваться, если не будет достаточно энтропии.

В Windows я не уверен насчет такого устройства, поэтомуон может откатиться к некоторому PRNG, который требует какого-то начального числа.

Чтобы решить проблему кросс-платформенно, как упоминал @Binara, вы можете использовать std::rand из <cstdlib>.Эта функция не блокируется, и вы можете использовать std::srand(somethingLikeCurrentTime), чтобы сделать ее кое-чем недетерминированной.

Как уже упоминалось @ user1118321, если вы хотите использовать более защищенный PRNG, вы можете рассмотреть std::mersenne_twister_engine и использовать std::random_device для генерации его начального числа.Этот подход предлагается здесь .

...