需求:
前几天写程序时有一个需求是随机生成1000000个[0,1000000)之间的随机整数,当然首选是rand()和srand()。但是后来我查看生成的数据时发现,有很多数据都是3万多,但是没有4万以上的数据,这不符合常理。然后试验了几次后发现还是一样的情况,然后我就百度了一下,结果发现rand()生成的最大整数是32767,也就是说,我们使用rand()生成随机数的范围只能是[0,32767),这显然不符合要求。下面是解决方法:
法一:
我在网上找了一下方法,发现了一种比较靠谱的方法,于是就试了试。语句是这样的:
(int) ((double)rand() / RAND_MAX) * 1000000;
RAND_MAX是C标准库中的一个宏,是<stdlib.h>中伪随机数生成函数rand()所能返回的最大数值,值为32767。上面语句的主要思路是,生成一个[0,1]范围内的double型随机数,然后乘以你需要的范围的最大值,比如我的话就乘1000000,之后取整一下得到的就是[0,1000000)。思路我觉得很正确,然后我就用这个方法生成了1000000个随机数,然后生成结果见下图:

图中每一行是随机生成的两个数,相当于我一次生成了1000000对数据,不过这不重要,每行的第一个数据是有序的(当然在这里为了能看清数据的规律,所以删掉了一部分数据),我们可以看出,第一列的数据是以30或31交替递增的。这是因为随机数出的整数相差1的话,1 / RAND_MAX = 0.000030518…,然后再乘以1000000后,差值为30.518,取整之后,差值由于累加的缘故,所以可能是30,也可能是31。
所以在这里,虽然理论上这种方法是可行的,但是实际上它并不能以均等的概率取到随机的整数。所以这里我想到了第二种方法,虽然看起来可能有一些繁琐,但是事实证明,是好用的,可以得到预期的结果。
法二:
这个方法的主要思路是根据生成随机数的范围,确定随机数的最大位数,比如我这里生成的是[0,1000000)内的整数,这里的整数就是0-999999,随机整数最大位数为6位。这里我们将每一个位数看做是一个随机数,事实上每一位就是一个随机数,说到这里大家可能就懂了,就是分别产生每一位对应的随机数,然后通过流拼接到一起,构成我们需要的随机数。下面附上代码(以生成[0,1000000)之间的随机数为例):
#include <iostream>
#include <stdlib.h>
#include <ctime>;
#include <string>
#include <sstream>
using namespace std;
int main(){
int u;
int * u_arr;
string u_str;
u_arr = new int[6];
srand((unsigned int)(time(NULL)));
for(int i = 0; i <10; i++){
stringstream ss;
u_arr[0] = rand() % 10;
u_arr[1] = rand() % 10;
u_arr[2] = rand() % 10;
u_arr[3] = rand() % 10;
u_arr[4] = rand() % 10;
u_arr[5] = rand() % 10;
ss << u_arr[0] << u_arr[1] << u_arr[2] << u_arr[3] << u_arr[4] <<u_arr[5];
ss >> u_str;
u = atoi(u_str.c_str());
cout << u << endl;
}
return 0;
}
运行结果如下图所示:

而且通过结果我们可以看出,当高位为0时是不会显示的,和正常的int型数据一样。
法三:
第二种方法可以用,但是我始终觉得太麻烦了,需要多次赋值,还需要将数据在不同类型之间相互转换。后来一个同学给了我一个更简单的思路。先上代码:
#include <iostream>
#include <ctime>
#include <stdlib.h>
#include <cmath>
using namespace std;
void main(){
int num;
int totalNum;
srand((unsigned int)(time(NULL)));
for(int i = 0; i < 10; i++){
totalNum = 0;
for(int j = 0; j < 6; j++){
num = rand() % 10;
totalNum += num * pow(10, j);
}
cout << totalNum << endl;
}
}
运行结果如下图所示:

这个方法和第二种方法的思路是类似的,只是第二种方法是通过流将生成的每个数拼接成一个完成的随机数,而这个方法是通过对生成的每个数乘10、100、…、100000来得到最终随机数上每一位上的值,然后想加后即可得到我们需要的随机数。个人觉得这个方法更好,看代码量就能看出来,而且第二种方法使用stringstream时,它不会自动释放内存,需要使用ss.str("")来主动释放内存,所以一不小心就会造成内存错误。
这是我第一次写博客,希望我的一些经验可以帮助到大家。如果大家觉得我说的有问题,也欢迎指正!
3246





