C ++快速随机数生成器

时间:2014-05-23 20:54:48

标签: c++

如果这是一个愚蠢的问题,我很抱歉,但我是c ++的新手,老实说找不到答案;

当我使用rand()时,我当然必须首先使用srand()。

首先,我只需导入<ctime>并执行srand(time()),这样就可以了。但是,如果我每秒拨打rand()一次以上 - time()频繁更改 - 那么我会得到相同的答案。所以例如;

#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;

int main()
{
    bool x = true;
    while(x == true)
    {
        int num = 1;
        srand(time(NULL));
        num = rand();
        cout<<num%10<<endl;
    }

}

可能会产生类似的东西,如6666666666777777777700000000003333333333

这对我的目的没有好处 - 我更喜欢像163509284749301935766这样的东西。

2 个答案:

答案 0 :(得分:7)

您应该只为随机数生成器播种一次。现在你正在循环中播种它并使用time(NULL)只意味着种子每秒更改一次,这会给你所描述的输出错误。

请改为:

int main()
{
    bool x = true;
    int num = 1;
    srand(time(NULL));
    while(x == true)
    {
        num = rand();
        cout<<num%10<<endl;
    }
}

如果你真的关心生成的随机数,你可能想要使用rand()之外的其他内容。原因是rand()的伪随机数生成的统计属性很差,它通常被实现为Linear congruential generator。如果你需要高质量的随机性,那么你应该更喜欢其他的东西,比如新的c ++随机数生成器http://en.cppreference.com/w/cpp/numeric/random。 实际上甚至有report on depreciating旧的rand()试图推动人们使用更新的c ++标准库随机函数。

在这种特殊情况下,你会得到一个导致一些微妙问题的模数:

num = rand();
cout<<num%10<<endl;

即使rand()完美,如果此处的模数不是rand()返回的最大值的除数,那么您将得到非均匀分布。这是一个快速解释,说rand()返回值在[0,25]范围内,然后取模数将执行以下操作。

before    after modulus 
[0-9]         [0-9]
[10-19]       [0-9]
[20-25]       [0-5]

你会发现你更有可能得到[0-5]而不是[6-9],这意味着你现在不再生成统一的数字了。请注意,这个小范围仅用于教育目的,标准要求rand()的最大值至少为32767.但是它说明了一个重点,最大生成数越大越好。

除了模数之外,这种均匀分布问题对于某些实现来说甚至进一步降低伪随机性的质量具有特别隐蔽的效果。

使用std::uniform_int_distribution避免了许多问题,因此我建议您更改现有代码以使用新库。这样做会是这样的:

#include <iostream>
#include <random>
using namespace std;

int main()
{
    std::default_random_engine generator;
    generator.seed( /* your seed for the RNG goes here */ );
    std::uniform_int_distribution<int> distribution(0,9);//note the min and max parameters are inclusive here
    while(true)
    {
        cout << distribution(generator) << endl;
    }

}

答案 1 :(得分:4)

使用c ++ 11库设施可以轻松,稳健,安全地定义能够生成 [low,high] 范围内随机数的函数f()

#include <random>
#include <iostream>

int f(int low, int high)
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(low, high);

    return dis(gen);
}

std::uniform_int_distribution会以这种方式为您提供范围内的随机数(例如(0,9))

关于不使用旧版rand背后的理由,您可以查看this