C++ need a good technique for seeding rand() that does not use time()

↘锁芯ラ 提交于 2019-11-29 10:44:56

You use a random number seed if and only if you want reproducible results. This can be handy for things like map generation where you want the map to be randomized, but you want it to be predictably random based on the seed.

For most cases you don't want that, you want actually random numbers, and the best way to do that is through the Standard Library generator functions:

#include <random>

std::random_device rd;
std::map<int, int> hist;
std::uniform_int_distribution<int> dist(0, 5);

int random_die_roll = dist(rd);

No seed is required nor recommended in this case. The "random device" goes about seeding the PRNG (pseudo random number generator) properly to ensure unpredictable results.

Again, DO NOT use srand(time(NULL)) because it's a very old, very bad method for initializing random numbers and it's highly predictable. Spinning through a million possible seeds to find matching output is trivial on modern computers.

Use a random seed to a pseudorandom generator.

std::random_device is expensive random data. (expensive as in slow) You use that to seed a prng algorithm. mt19937 is the last prng algorithm you will ever need.

You can optionally follow that up by feeding it through a distribution if your needs require it. i.e. if you need values in a certain range other than what the generator provides.

std::random_device rd;
std::mt19937 generator(rd());

These days rand() and srand() are obsolete.

The generally accepted method is to seed a pseudo random number generator from the std::random_device. On platforms that provide non-deterministic random sources the std::random_device is required to use them to provide high quality random numbers.

However it can be slow or even block while gathering enough entropy. For this reason it is generally only used to provide the seed.

A high quality but efficient random engine is the mersenne twister provided by the standard library:

inline
std::mt19937& random_generator()
{
    thread_local static std::mt19937 mt{std::random_device{}()};
    return mt;
}

template<typename Number>
Number random_number(Number from, Number to)
{
    static_assert(std::is_integral<Number>::value||std::is_floating_point<Number>::value,
        "Parameters must be integer or floating point numbers");

    using Distribution = typename std::conditional
    <
        std::is_integral<Number>::value,
        std::uniform_int_distribution<Number>,
        std::uniform_real_distribution<Number>
    >::type;

    thread_local static Distribution dist;

    return dist(random_generator(), typename Distribution::param_type{from, to});
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!