在C ++中生成一个统一的随机整数

时间:2013-04-22 17:55:29

标签: c++ random

问题是我需要生成0到999之间的随机整数(用于调查数学猜想)。所有的值都需要具有相同的概率。

我尝试了rand(),但RAND_MAX为32767(在我的编译器上),这意味着只需要rand() % 1000导致第一个1-767更有可能出现(并且假设所有可能性在rand()中具有相同的概率)。

我正在使用Windows,因此/dev/random不是一个选项。

6 个答案:

答案 0 :(得分:19)

您可以使用uniform_int_distribution和C ++ 11执行类似的操作:

#include <iostream>
#include <random>

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 999);

    for (int n=0; n<1000; ++n)
        std::cout << dis(gen) << ' ';
    std::cout << '\n';
}

答案 1 :(得分:9)

你的模数观察是正确的,并且rand()不能完成数学审查的几个原因之一。来自the notes here

  

无法保证产生的随机序列的质量。在过去,rand()的一些实现在所产生的序列的随机性,分布和周期中具有严重的缺点(在一个众所周知的示例中,低阶位简单地在调用之间在1和0之间交替)。 rand()不建议用于严重的随机数生成需求,如加密。

C ++ 11引入了several new random number generators,它符合更严格的标准,可能适合您的目的。

如果您可以牺牲超过几个字节的开销(可以安全地假设您可以),我建议std::mersenne_twister_engine

答案 2 :(得分:3)

我认为最简单的方法是在[32000, 32767]区间内丢弃数字,并仅将% 1000应用于其余数字。这可以让你获得更均匀的分布。

或者你可以使用boost的随机/均匀分布组件(如果可用的话,可以使用C ++ 11),因为这些组件将提供比rand更健全的PRNG。

答案 3 :(得分:2)

计算机中没有“真正随机”的东西。我也不相信1-767(或技术上,0-767,在这种情况下)的可能性明显高于任何其他数字。但是,如果你需要“更好”的随机数,那么C ++ 11支持使用Mersenne Twister,这是一个更高等级的随机数发生器。

此处提供更多信息: http://www.cplusplus.com/reference/random/mt19937/

答案 4 :(得分:1)

问题是rand()为域[0,RAND_MAX]提供了统一分布式变量,RAND_MAX最有可能是32767.您无法通过简单的乘法将此域映射到更大的域

u=(double)rand();
d=(double)RAND_MAX;
double div= u/d;
double res=div*interval_range;

因为只有当RAND_MAX是interval_range的偶数倍时,这才是正确的。但是,您不会在更大的域中拥有所有值。但是,如果您所需的新域名小于RAND_MAX,则可以将rand()生成的统一分布截断到所需的域名(实质上意味着拒绝rand()值大于您的期望的域名)。截断的均匀分布仍然是均匀的,因此您将在新域上使用新的均匀分布变量(这将更精确地为条件分布)。统计例子:

enter image description here

所以截断的均匀分布将有另一个“时刻”,描述它的参数(均值,std_dev,方差等),但会再次统一。

示例代码:

int main{ 
    int o=RAND_MAX;
    std::map<int,int> m1;
    int min=0,max=999;

    for (int i=0; i<1000*9994240; ++i){//9994240=305*32768  32768=RAND_MAX+1
        int r=rand();
        if(r<=max){
            m1[r]++;
        }
    }
    for (auto & i : m1)
        std::cout << i.first << " : " << i.second << '\n';
}

结果: 0:42637 1:42716 2:42590 3:42993 4:42936 5:42965 6:42941 7:42705 8:42944 9:42707 10:42860 11:43012 12:42793 // ... 995:42861 996:42911 997:42865 998:42877 999:43159


您可以通过以下方式在任何域上获得所需的结果:

#include <iostream>
#include <random>

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 1000);

    for (int n=0; n<1000; ++n)
        std::cout << dis(gen) << ' ';
    std::cout << '\n';
}

但是你应该在这种情况下使用boost:

#include <iostream>
#include "boost/random.hpp"
#include "boost/generator_iterator.hpp"
using namespace std;

int main() {
      typedef boost::mt19937 RNGType;
      RNGType rng;
      boost::uniform_int<> zero_to_n( 0, 999 );
      boost::variate_generator< RNGType, boost::uniform_int<> >
                    dice(rng, zero_to_n);
          int n  = dice();

}

答案 5 :(得分:0)

  1. 使用rand()获取随机数。

  2. 将其除以RAND_MAX。您将获得0到1之间的浮点数。

  3. 将此数字乘以1000。