问题是我需要生成0到999之间的随机整数(用于调查数学猜想)。所有的值都需要具有相同的概率。
我尝试了rand()
,但RAND_MAX
为32767(在我的编译器上),这意味着只需要rand() % 1000
导致第一个1-767更有可能出现(并且假设所有可能性在rand()
中具有相同的概率)。
我正在使用Windows,因此/dev/random
不是一个选项。
答案 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()
值大于您的期望的域名)。截断的均匀分布仍然是均匀的,因此您将在新域上使用新的均匀分布变量(这将更精确地为条件分布)。统计例子:
所以截断的均匀分布将有另一个“时刻”,描述它的参数(均值,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)
使用rand()
获取随机数。
将其除以RAND_MAX
。您将获得0到1之间的浮点数。
将此数字乘以1000。