What's the standard way for getting uniformly

2019-02-06 15:28发布

Is there a function for obtaining uniformly distributed pseudo-random integers in some specified range? I could write my own function using rand, but this seems like a common enough situation that there's probably something in the STL for it.

标签: c++ random
3条回答
我想做一个坏孩纸
2楼-- · 2019-02-06 15:46

Boost provides many tools for random number generation. For uniform distributions you have this one:

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

EDIT: updated to include the new C++11 implementation. For the case of integers, here you have the reference:

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

A simple example would be:

#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';
}
查看更多
倾城 Initia
3楼-- · 2019-02-06 15:46

To generate pseudo-random numbers in C++, a very good option is using the Mersenne twister pseudo-random number generator engine: std::mt19937 from the <random> header.

We can think of this engine as a black-box that spits out high-quality random bits.

Then, these random bits can be shaped in some integers output using a distribution; in particular, to get uniformly distributed pseudo-random numbers, a std::uniform_int_distribution can be used.

Note that the engine object must be initialized with a seed.
std::random_device can be used for that purpose.

So, this process can be summarized in three logical steps:

  1. Create an instance of std::random_device, to get a non-deterministic seed for the Mersenne twister engine.
  2. Create an instance of std::mt19937 engine, to get high-quality pseudo-random bits.
  3. Use a std::uniform_int_distribution to shape these random bits in uniformly-distributed integers.

Compilable C++ code follows:

#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's 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;
}

For more details on generating pseudo-random numbers in C++ (including reasons why rand() is not good), see this video by Stephan T. Lavavej (from Going Native 2013):

rand() Considered Harmful

查看更多
混吃等死
4楼-- · 2019-02-06 16:03

To generate one or specified number of random variables with uniform distribution on integer domain using std::generate_n and 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;
}
查看更多
登录 后发表回答