Каков стандартный способ получения равномерно распределенных случайных целых чисел в С++?

Есть ли функция для получения равномерно распределенных псевдослучайных целых чисел в некотором заданном диапазоне? Я мог бы написать свою собственную функцию, используя rand, но это кажется довольно распространенной ситуацией, что, возможно, что-то в STL для нее.

Ответ 1

Boost предоставляет множество инструментов для генерации случайных чисел. Для равномерных распределений вы имеете следующее:

http://www.boost.org/doc/libs/1_49_0/doc/html/boost/random/uniform_real_distribution.html

EDIT: обновлен, чтобы включить новую реализацию С++ 11. Для целых чисел здесь вы имеете ссылку:

http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution

Простым примером может быть:

#include <random>
#include <iostream>
int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(1, 6);
    for(int n=0; n<10; ++n)
        std::cout << dis(gen) << ' ';
    std::cout << '\n';
}

Ответ 2

Чтобы генерировать псевдослучайные числа в С++, очень хороший вариант - использовать механизм генерации псевдослучайных чисел Mersenne twister: std::mt19937 из заголовка <random>.

Мы можем думать об этом двигателе как о черном ящике, который выплескивает высококачественные случайные биты.

Затем эти случайные биты могут быть сформированы на выходе некоторых целых чисел с использованием распределения; в частности, для получения равномерно распределенных псевдослучайных чисел, можно использовать std::uniform_int_distribution.

Обратите внимание, что объект движка должен быть инициализирован семенем.
std::random_device может использоваться для этой цели.

Итак, этот процесс можно суммировать тремя логическими шагами:

  • Создайте экземпляр std::random_device, чтобы получить недетерминированное семя для движка Twers Mersenne.
  • Создайте экземпляр механизма std::mt19937, чтобы получить высококачественные псевдослучайные биты.
  • Используйте std::uniform_int_distribution для формирования этих случайных бит в равномерно распределенных целых числах.

Скомпилированный код С++:

#include <iostream>     // for console output
#include <random>       // for pseudo-random number generators and distributions

int main()
{
    // Use random_device to generate a seed for Mersenne twister engine.
    std::random_device rd;    

    // Use Mersenne twister engine to generate pseudo-random numbers.
    std::mt19937 engine(rd());

    // "Filter" MT engine output to generate pseudo-random integer values,
    // **uniformly distributed** on the closed interval [0, 99].  
    // (Note that the range is [inclusive, inclusive].)
    std::uniform_int_distribution<int> dist(0, 99);

    // Generate and print 10 pseudo-random integers
    for (int i = 0; i < 10; ++i)
    {
        std::cout << dist(engine) << ' ';
    }
    std::cout << std::endl;
}

Подробнее о генерации псевдослучайных чисел в С++ (включая причины, по которым rand() не очень хорошо), см. это видео Stephan T. Lavavej (from Going Native 2013):

rand() Считается вредным

Ответ 3

Чтобы создать одно или определенное количество случайных величин с равномерным распределением по целочисленной области с помощью std::generate_n и boost:

#include <iostream>
#include <algorithm>
#include <boost/random.hpp>

/*
 * 
 */
int main(int argc, char** argv) {
    boost::mt19937 rand_generator(std::time(NULL));
    boost::random::uniform_int_distribution<> int_distribution(0, 100);

    //Need to pass generator
    std::cout << int_distribution(rand_generator) << std::endl;

    //Associate generator with distribution
    boost::random::variate_generator<boost::mt19937&,
            boost::random::uniform_int_distribution<>
            > int_variate_generator(rand_generator, int_distribution);

    //No longer need to pass generator
    std::cout << int_variate_generator() << std::endl;
    std::generate_n( std::ostream_iterator<int>(std::cout, ","), 3, int_variate_generator);
    return 0;
}