C++ 为什么使用rand()会有更高的概率
我猜是个奇怪的问题。这是出于好奇 使用rand()函数,如果我们将参数设置在1-10之间,那么我会在我的机器UNIX操作系统(更具体地说是Ubuntu)上运行几次测试。我的结果总是显示返回的数字越大(大于5)。看起来一点也不像是随机的 我还读了关于模的内容,其中指出,使用模运算,我们形成了某种偏差 但请注意,此模运算不会在跨度中生成均匀分布的随机数(因为在大多数情况下,此运算使较低的数字更可能) 为什么呢?它还说,数字越低越有可能,但我得到的数字越高如何测试偏差 系统上的C++ 为什么使用rand()会有更高的概率,c++,c,unix,random,C++,C,Unix,Random,我猜是个奇怪的问题。这是出于好奇 使用rand()函数,如果我们将参数设置在1-10之间,那么我会在我的机器UNIX操作系统(更具体地说是Ubuntu)上运行几次测试。我的结果总是显示返回的数字越大(大于5)。看起来一点也不像是随机的 我还读了关于模的内容,其中指出,使用模运算,我们形成了某种偏差 但请注意,此模运算不会在跨度中生成均匀分布的随机数(因为在大多数情况下,此运算使较低的数字更可能) 为什么呢?它还说,数字越低越有可能,但我得到的数字越高如何测试偏差 系统上的rand()生成器(gl
rand()
生成器(glibc中的生成器)存在问题,但过度偏差不在其中。假设您使用以下代码生成给定范围内的随机数
int random_int(int min, int max)
{
return min + rand() % (max - min + 1);
}
我们不要假设你是数字的种子
int main(int argc, char **argv)
{
int histo[10];
for (int i = 0; i < 10; i++)
histo[i] = 0;
for (int i = 0; i < 10000; i++)
histo[random_int(1, 10) - 1]++;
for (int i = 0; i < 10; i++)
printf("%d\n", histo[i]);
}
int main(int argc,char**argv)
{
int-histo[10];
对于(int i=0;i<10;i++)
histo[i]=0;
对于(int i=0;i<10000;i++)
histo[random_int(1,10)-1]+;
对于(int i=0;i<10;i++)
printf(“%d\n”,histo[i]);
}
这将给我们10000个样品,虽然小但可行。我得到以下结果。如果您使用的是同一版本的glibc,您将得到完全相同的结果
1053
980
1002
959
1009
948
1036
1041
987
985
1053
980
1002
959
1009
948
1036
1041
987
985
在给定无偏生成器的情况下,我们期望箱子遵循二项式分布。对于10000个样本,我们预计每箱方差为Np(1-p)或900,其标准偏差正好为30。我们的样本差异是1105。现在,我不会在这里做任何严格的事情。。。我要假设二项分布是正态的。。。我要做一个简单的卡方检验。结果为p=0.2。不完全是诅咒
因此,如果你想测试你的随机数生成器,记得在测试结束后做数学运算来解释测试结果
模偏差
模偏差实际上增加了较低数字的概率,而不是较高数字的概率。对于这样的范围(1..10),偏差非常小,因为glibc的RAND_MAX
为231-1,这使得小数字的概率增加了大约2亿分之一。您需要执行大量的测试以暴露模偏差
不鼓励模运算的主要原因是因为公共rand()
实现的低位独立性较差。当然,您也不应该使用此技术生成大范围
建议
如果你真的想测试你的随机数生成器,我建议看看已故的Marsaglia的“顽固”测试。如果您只是想要一个好的随机数生成器,可以使用arc4random、Mersenne Twister或/dev/uradom
。您的选择将根据您是开发加密应用程序还是使用蒙特卡罗模拟结果而有所不同。如何测试偏差
系统上的rand()
生成器(glibc中的生成器)存在问题,但过度偏差不在其中。假设您使用以下代码生成给定范围内的随机数
int random_int(int min, int max)
{
return min + rand() % (max - min + 1);
}
我们不要假设你是数字的种子
int main(int argc, char **argv)
{
int histo[10];
for (int i = 0; i < 10; i++)
histo[i] = 0;
for (int i = 0; i < 10000; i++)
histo[random_int(1, 10) - 1]++;
for (int i = 0; i < 10; i++)
printf("%d\n", histo[i]);
}
int main(int argc,char**argv)
{
int-histo[10];
对于(int i=0;i<10;i++)
histo[i]=0;
对于(int i=0;i<10000;i++)
histo[random_int(1,10)-1]+;
对于(int i=0;i<10;i++)
printf(“%d\n”,histo[i]);
}
这将给我们10000个样品,虽然小但可行。我得到以下结果。如果您使用的是同一版本的glibc,您将得到完全相同的结果
1053
980
1002
959
1009
948
1036
1041
987
985
1053
980
1002
959
1009
948
1036
1041
987
985
在给定无偏生成器的情况下,我们期望箱子遵循二项式分布。对于10000个样本,我们预计每箱方差为Np(1-p)或900,其标准偏差正好为30。我们的样本差异是1105。现在,我不会在这里做任何严格的事情。。。我要假设二项分布是正态的。。。我要做一个简单的卡方检验。结果为p=0.2。不完全是诅咒
因此,如果你想测试你的随机数生成器,记得在测试结束后做数学运算来解释测试结果
模偏差
模偏差实际上增加了较低数字的概率,而不是较高数字的概率。对于这样的范围(1..10),偏差非常小,因为glibc的RAND_MAX
为231-1,这使得小数字的概率增加了大约2亿分之一。您需要执行大量的测试以暴露模偏差
不鼓励模运算的主要原因是因为公共rand()
实现的低位独立性较差。当然,您也不应该使用此技术生成大范围
建议
如果你真的想测试你的随机数生成器,我建议看看已故的Marsaglia的“顽固”测试。如果您只是想要一个好的随机数生成器,可以使用arc4random、Mersenne Twister或/dev/uradom
。您的选择将根据您是开发加密应用程序还是使用蒙特卡罗模拟结果而有所不同。如何测试偏差
系统上的rand()
生成器(glibc中的生成器)存在问题,但过度偏差不在其中。假设您使用以下代码生成给定范围内的随机数
int random_int(int min, int max)
{
return min + rand() % (max - min + 1);
}
我们不要假设你是数字的种子
int main(int argc, char **argv)
{
int histo[10];
for (int i = 0; i < 10; i++)
histo[i] = 0;
for (int i = 0; i < 10000; i++)
histo[random_int(1, 10) - 1]++;
for (int i = 0; i < 10; i++)
printf("%d\n", histo[i]);
}
int main(int argc,char**argv)
{
int-histo[10];
对于(int i=0;i<10;i++)
histo[i]=0;
对于(int i=0;i<10000;i++)
历史[随机]