[英]rand() gives still the same value
我注意到,通过做一个简单的基于控制台的测验应用程序练习。 当我使用rand()
它连续几次给我相同的值。 数字范围越小,问题就越大。
例如
for (i=0; i<10; i++) {
x = rand() % 20 + 1;
cout << x << ", ";
}
会给我1,1,1,2,1,1,1,1,14 1, 1, 1, 2, 1, 1, 1, 1, 14,
- 有太多的,对吧? 我通常从没有到4个奇数(休息是一样的,也可以是11, 11, 11, 4, 11 ...
)
难道我做错了什么? 或者rand()
不是那么随意我认为是这样吗?
(或者它只是来自C#/ Java的一些我不知道的习惯?它对我来说也发生了很多......)
如果我运行该代码几次,我得到不同的输出。 当然,并不像我想的那样变化,但看似不确定(虽然当然是,因为rand()
只给出伪随机数......)。
但是,你对待你的数字的方式不会给你一个均匀的分布超过[1,20],我想这就是你所期望的。 要实现这一目标要复杂得多,但绝不可能。 例如,请查看cplusplus.com上<random>
的文档 - 在底部有一个展示程序,它在[0,1)上生成均匀分布。 要获得[1,20],您只需将输入参数更改为生成器 - 它可以为您提供您喜欢的任何范围内的均匀分布。
我做了一个快速测试,并称为rand()
一百万次。 正如您在下面的输出中所看到的,即使样本量非常大,分布中也存在一些不均匀性。 当样本数量变为无穷大时,该行将(可能)变平,使用rand() % 20 + 1
会给你一个需要很长时间才能完成的分布。 如果您采取其他措施(如上面的示例),即使样本量非常小,您也可以更好地实现均匀分布。
编辑:
我看到其他几个人发布了关于使用srand()
在使用它之前播种随机数生成器的问题。 这是一个很好的建议,但在这种情况下它不会解决您的问题。 我再说一遍: 在这种情况下播种不是问题。
种子主要用于控制程序输出的可重复性。 如果使用常量值(例如0)对随机数进行种子处理,程序将每次都给出相同的输出,这对于测试一切都按照应有的方式进行测试非常有用。 通过播种非常量(当前时间是一种流行的选择),您可以确保结果在不同的程序运行之间有所不同。
完全不调用srand()
与使用C ++标准调用srand(1)
相同。 因此,每次运行程序时都会得到相同的结果,但每次运行中都会有一系列完全有效的伪随机数。
听起来你正在达到模数偏见 。
使用%
将随机数缩放到范围不是一个好主意。 如果你将它降低到2的幂,但仍然相当差,这几乎是可以接受的。 它主要受较小的比特的影响,这些比特通常随着许多算法(特别是rand()
而随机性较小,并且它以非均匀的方式收缩到较小的范围,因为你的缩小范围不会平均分割范围您的随机数生成器。 要缩小范围,您应该使用除法和循环,如下所示:
// generate a number from 0 to range-1
int divisor = MAX_RAND/(range+1);
int result;
do
{
result = rand()/divisor;
} while (result >= range);
这并不像它看起来那么低效,因为循环几乎总是只传递一次。 此外,如果你打算将你的发生器用于接近MAX_RAND
数字,你需要一个更复杂的divisor
方程式,这是我无法记得的。
另外, rand()
是一个非常差的随机数生成器,如果你关心结果的质量,可以考虑使用像Mersenne Twister这样的东西。
您需要先调用srand()
并为其提供更好的伪随机值的参数时间。
例:
#include <iostream>
#include <string>
#include <vector>
#include "stdlib.h"
#include "time.h"
using namespace std;
int main()
{
srand(time(0));
int x,i;
for (i=0; i<10; i++) {
x = rand() % 20 + 1;
cout << x << ", ";
}
system("pause");
return 0;
}
如果您不希望重复生成的任何数字并且不需要考虑内存,则可以使用整数vector
,随机对其进行随机播放,然后获取前N个int的值。
例:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
//Get 5 random numbers between 1 and 20
vector<int> v;
for(int i=1; i<=20; i++)
v.push_back(i);
random_shuffle(v.begin(),v.end());
for(int i=0; i<5; i++)
cout << v[i] << endl;
system("pause");
return 0;
}
可能的问题是你每次都使用相同的“随机”数字,并且任何int
mod 1都是零。 换句话说(myInt % 1 == 0
)总是如此。 而不是%1
,使用% theBiggestNumberDesired
。
另外,用srand
播种你的随机数。 使用常量种子来验证您是否获得了良好的结果。 然后更改种子以确保您仍然获得良好的结果。 然后使用更随机的种子,如时钟进一步奶嘴。 随机种子释放。
注意:如果你在不同的线程中运行它而没有调用srand(),rand()会给你相同的结果。 试试这个看看自己:
vector<thread> workers;
for (int i = 0; i < 10; i++)
workers.push_back(std::thread([]{ cout << rand() << endl; }));
for (auto& th : workers)
{
if (th.joinable())
th.join();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.