Подтвердить что ты не робот

Случайные числа в С++ 0x

Новый стандарт С++ 11 имеет целую главу, посвященную генераторам случайных чисел. Но как мне выполнить простейшую, наиболее распространенную задачу, которая раньше кодировалась таким образом, но не прибегая к стандартной библиотеке C:

srand((unsigned int)time(0));
int i = rand();

Существуют ли разумные значения по умолчанию для двигателей, распределений и семян случайных чисел, которые можно использовать из коробки?

4b9b3361

Ответ 1

Вы должны иметь возможность сделать что-то вроде:

std::default_random_engine e((unsigned int)time(0));
int i = e();

Качество default_random_engine зависит от реализации. Вы также можете использовать std::min_rand0 или std::min_rand.

Вероятно, лучший способ засеять случайный движок - это как истинное случайное число, которое доступно из реализации, а не использовать time.

например.

std::random_device rd;
std::default_random_engine e( rd() );

Ответ 2

Объединяя и упрощая некоторые из уже представленных образцов, я подведу итог:

// Good random seed, good engine
auto rnd1 = std::mt19937(std::random_device{}());

// Good random seed, default engine
auto rnd2 = std::default_random_engine(std::random_device{}());

// like rnd1, but force distribution to int32_t range
auto rnd3 = std::bind(std::uniform_int_distribution<int32_t>{}, std::mt19937(std::random_device{}()));

// like rnd3, but force distribution across negative numbers as well
auto rnd4 = std::bind(std::uniform_int_distribution<int32_t>{std::numeric_limits<int32_t>::min(),std::numeric_limits<int32_t>::max()}, std::mt19937(std::random_device{}()));

Затем я провел несколько тестов, чтобы увидеть, как выглядят по умолчанию:

#include <random>
#include <functional>
#include <limits>
#include <iostream>

template<class Func>
void print_min_mean_max(Func f) {
   typedef decltype(f()) ret_t;
   ret_t min = std::numeric_limits<ret_t>::max(), max = std::numeric_limits<ret_t>::min();
   uint64_t total = 0, count = 10000000;
   for (uint64_t i = 0; i < count; ++i) {
      auto res = f();
      min = std::min(min,res);
      max = std::max(max,res);
      total += res;
   }
   std::cout << "min: " << min << " mean: " << (total/count) << " max: " << max << std::endl;
}

int main() {
   auto rnd1 = std::mt19937(std::random_device{}());
   auto rnd2 = std::default_random_engine(std::random_device{}());

   auto rnd3 = std::bind(std::uniform_int_distribution<int32_t>{}, std::mt19937(std::random_device{}()));
   auto rnd4 = std::bind(std::uniform_int_distribution<int32_t>{std::numeric_limits<int32_t>::min(),std::numeric_limits<int32_t>::max()}, std::mt19937(std::random_device{}()));

   print_min_mean_max(rnd1);
   print_min_mean_max(rnd2);
   print_min_mean_max(rnd3);
   print_min_mean_max(rnd4);
}

Производит вывод:

min: 234 mean: 2147328297 max: 4294966759
min: 349 mean: 1073305503 max: 2147483423
min: 601 mean: 1073779123 max: 2147483022
min: -2147481965 mean: 178496 max: 2147482978

Итак, как мы видим, mt19937 и default_random_engine имеют разные значения по умолчанию, поэтому рекомендуется использовать равномерное_распределение.

Кроме того, стандартное равномерное_информация равно [0, max_int] (неотрицательно) даже при использовании целочисленного типа со знаком. Должен задавать диапазон явно, если вы хотите полный диапазон.

Наконец, важно помнить об этом в такие моменты.

Ответ 3

Если ваш существующий код был подходящим перед новым стандартом, он будет по-прежнему оставаться. Новые генераторы случайных чисел были добавлены для приложений, для которых требуется более высокое качество псевдослучайности, например. стохастическое моделирование.

Ответ 4

Я использую следующий код в своем проекте. "двигатель" и "распространение" могут быть предоставлены библиотекой.

#include <random>
#include <functional>
#include <iostream>
...
std::uniform_int_distribution<unsigned int> unif;
std::random_device rd;
std::mt19937 engine(rd());
std::function<unsigned int()> rnd = std::bind(unif, engine);

std::cout << rnd() << '\n';

Ответ 5

Здесь вы идете. Случайные удвоения в диапазоне:

// For ints
// replace _real_ with _int_, 
// <double> with <int> and use integer constants

#include <random>
#include <iostream>
#include <ctime>
#include <algorithm>
#include <iterator>

int main()
{
    std::default_random_engine rng(std::random_device{}()); 
    std::uniform_real_distribution<double> dist(-100, 100);  //(min, max)

    //get one
    const double random_num = dist(rng);

    //or..
    //print 10 of them, for fun.
    std::generate_n( 
        std::ostream_iterator<double>(std::cout, "\n"), 
        10, 
        [&]{ return dist(rng);} ); 
    return 0;
}

Ответ 6

Генерация случайных чисел - сложная проблема. Нет действительно случайного способа сделать это. Если вы просто генерируете случайность для посева игровой среды, то ваш подход должен быть прекрасным. rand() имеет несколько недостатков.

Если вам нужна случайность для генерации ключей шифрования, тогда вы S.O.L. Лучший способ в этом случае - выйти в операционную систему, которая обычно имеет механизм. В POSIX это random() (или прочитайте из /dev/random, если вы так настроены). В Windows вы можете использовать CryptoAPI:

https://www.securecoding.cert.org/confluence/display/seccode/MSC30-C.+Do+not+use+the+rand%28%29+function+for+generating+pseudorandom+numbers

Ответ 7

Вы можете использовать RC4 для генерации случайных байтов. Вероятно, у этого есть свойства, которые вы хотите. Это быстро и довольно просто реализовать. Последовательность повторяется во всех реализациях, когда семя известно и совершенно непредсказуемо, когда семя неизвестно. http://en.wikipedia.org/wiki/RC4