C ++需要一个很好的技术来播种不使用time()的rand()

时间:2018-06-03 00:21:49

标签: c++ random random-seed

我有一个启动许多客户端进程的bash脚本。这些是人工智能游戏玩家,我用它来测试一个拥有400个连接的玩家的游戏。

我遇到的问题是AI播放器使用

srand( time(nullptr) );

但如果所有玩家大约在同一时间开始,他们将经常收到相同的time()值,这意味着他们都在同一个rand()序列中。

测试过程的一部分是确保如果大量客户端几乎同时尝试连接,服务器就可以处理它。

我曾考虑使用像

这样的东西
srand( (int) this );

或类似的,基于每个实例都有唯一内存地址的想法。

还有另一种更好的方式吗?

3 个答案:

答案 0 :(得分:3)

将随机种子用于伪随机生成器。

std::random_device是昂贵的随机数据。 (昂贵,如慢) 您可以使用它来播种prng算法。 mt19937是您需要的最后一个prng算法。

如果您的需求需要,您可以选择通过分发方式进行操作。即如果您需要的值不是发电机提供的某个范围。

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

答案 1 :(得分:3)

这些天rand()srand()已过时。

普遍接受的方法是从std::random_device播种伪随机数生成器。在提供非确定性随机源的平台上,std::random_device需要使用它们来提供高质量的随机数。

然而,在收集足够的熵时它可能很慢甚至阻塞。因此,它通常仅用于提供种子。

高质量但高效的随机引擎是标准库提供的 mersenne twister

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});
}

答案 2 :(得分:2)

如果您想要可重现的结果,则使用随机数种子和。这对于地图生成这样的事情来说非常方便,你想让地图随机化,但你希望它可以根据种子预测为随机。

对于大多数情况,你不想要它,你想要实际的随机数,最好的方法是通过标准库生成器函数:

#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);

在这种情况下,不需要也不推荐种子。 &#34;随机设备&#34;关于正确播种PRNG(伪随机数发生器)以确保不可预测的结果。

同样,不要使用srand(time(NULL)),因为它是一种非常古老,非常糟糕的初始化随机数的方法,并且它具有高度可预测性。在现代计算机上,通过一百万种可能的种子来寻找匹配的输出是微不足道的。