C++中用rand()生成大随机数

需求:

前几天写程序时有一个需求是随机生成1000000个[0,1000000)之间的随机整数,当然首选是rand()和srand()。但是后来我查看生成的数据时发现,有很多数据都是3万多,但是没有4万以上的数据,这不符合常理。然后试验了几次后发现还是一样的情况,然后我就百度了一下,结果发现rand()生成的最大整数是32767,也就是说,我们使用rand()生成随机数的范围只能是[0,32767),这显然不符合要求。下面是解决方法:

法一:

我在网上找了一下方法,发现了一种比较靠谱的方法,于是就试了试。语句是这样的:

(int) ((doublerand() / 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("")来主动释放内存,所以一不小心就会造成内存错误。
这是我第一次写博客,希望我的一些经验可以帮助到大家。如果大家觉得我说的有问题,也欢迎指正!

评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值