我尝试使用rand()函数,但由于RAND_MAX在我的编译器上为32767,这意味着仅执行rand() % 1000会导致前1-767个数出现的概率明显更高(假设所有可能性都具有相同的概率)。
由于我正在使用Windows操作系统,因此/dev/random不是一个选项。
您可以使用 C++11 中的 uniform_int_distribution
来实现类似以下方式的操作:
#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';
}
random_device
是一个非确定性pRNG(我相信基于Windows的加密服务)。 - bames53您的模数观察是正确的,这也是rand()
无法经受数学检验的几个原因之一。根据此处的说明:
不能保证产生的随机序列的质量。过去,一些rand()的实现在生成的序列的随机性、分布和周期方面存在严重缺陷(在一个众所周知的例子中,低位比特只是在调用之间交替地为1和0)。不建议使用rand()进行严格的随机数生成需求,例如加密。
C++11引入了几个新的随机数生成器,这些生成器遵循更严格的标准,很可能适合您的目的。
如果您可以牺牲超过几字节的开销(可以安全地假设您可以),我建议使用std::mersenne_twister_engine
我认为最简单的方法是将区间[32000,32767]
中的数字丢弃,只对其余数字应用% 1000
。这应该能得到更加均匀的分布。
另外,您也可以使用boost的随机/均匀分布组件(或者如果有的话,使用C++11),因为它们会提供比rand
更可靠的伪随机数生成器。
[0,RAND_MAX]
上均匀分布的变量,其中RAND_MAX
最可能是32767。你不能通过简单的乘法将此域映射到较大的域中。u=(double)rand();
d=(double)RAND_MAX;
double div= u/d;
double res=div*interval_range;
所以截断均匀分布会有另外的“矩”,描述它的参数(平均值、标准差、方差等)但仍然是均匀的。
示例代码:
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';
}
#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();
}
min+((double)rand()/(double)RAND_MAX)*(max-min)
会产生均匀分布?它仍然将 RAND_MAX
的输入映射到 max-min
的输出。因此,假设每个可能的输入都是等可能的,除非 RAND_MAX
能够被 max-min
均匀地整除,否则某些输出将比其他输出更有可能,因此它不是均匀的。我相信这就是MooingDuck投反对票的原因。 - Benjamin Lindley使用 rand()
函数获取一个随机数。
将其除以 RAND_MAX
,你会得到一个介于 0 和 1 之间的浮点数。
将这个数乘以 1000。
计算机中不存在“真正随机”的概念。我也不相信1-767(或在那种情况下,技术上是0-767)比任何其他数字有显着更高的机会。然而,如果您需要“更好”的随机数,那么C++11支持使用Mersenne Twister,这是一种更高级别的随机数生成器。
1000 * (((double)rand()) / RAND_MAX)
。 - Sergey Kalinichenko