随机数常见问题及解决方案

本人最近在做项目,用到了随机数生成器,遇到一些问题,做一下记录,如果有朋友遇到这样的问题,也可以参考解决之。
- - - - - - - - - - - - - - - - - - - - - - - - - - – - - - - - - - - – - - - -
1、运行多次,为什么每次生成的随机数都是同样的数字?如何生成不同数字?
2、如何随机生成指定范围内的数字?如何生成指定精度的随机数?
3、如何随机生成若干不同的数字,并将其存在数组中?
- - - - - - - - - - - - - - - - - - - - - - - - - - – - - - - - - - - – - - - -
随机数所涉及的头文件为stdlib.h和time.h,所涉及的函数为srand(),rand(),time(),现在通过实验代码解决以上问题。
步骤:使用srand(unsigned seed)函数设置随机数种子,然后使用rand()函数获取随机数。

1、运行多次,为什么每次生成的随机数都是同样的数字?如何生成不同数字?

看代码:
 #include <iostream>
 #include <stdlib.h>
 #include <time.h>
 
 using namespace std;
 
 int main(){
	int i,temp;
	for(i=0; i<10; i++){
		srand((unsigned)time(NULL)); //设置随机数种子
		
		temp = rand()%100; //生成100以内的随机数
		cout << temp<<" ";
	}
	cout<<endl;
	return 0;
 }

多次运行结果如下:
C:\Users…\Desktop>g++ ranom.cpp

C:\Users…\Desktop>a.exe
58 58 58 58 58 58 58 58 58 58

C:\Users…\Desktop>a.exe
84 84 84 84 84 84 84 84 84 84

C:\Users…\Desktop>a.exe
88 88 88 88 88 88 88 88 88 88

可以看到,每次运行的结果产生的随机数字都一样,这是因为虽然用srand函数设置了随机数种子,但是srand在for循环内部,由于for循环的运行速度很快,随机种子没有更换,也即种子相同,产生的随机数就相同。如果使用for循环产生不同的随机数就要把srand放到for循环之外,看如下代码:

 #include <iostream>
 #include <stdlib.h>
 #include <time.h>
 
 using namespace std;
 
 int main(){
	int i,temp;
	
	srand((unsigned)time(NULL)); //设置随机数种子
	
	for(i=0; i<10; i++){		
		temp = rand()%100; //生成100以内的随机数
		cout << temp<<" ";
	}
	cout<<endl;
	return 0;
 }

结果如下:
C:\Users…\Desktop>g++ ranom.cpp

C:\Users…\Desktop>a.exe
83 38 61 40 32 31 42 51 92 51

C:\Users…\Desktop>a.exe
89 67 21 31 93 84 66 96 47 55

C:\Users…\Desktop>a.exe
96 64 82 90 23 69 91 42 2 58

可以看到在每次运行结果内,数字基本不相同。关键点就是要把srand放到for循环外面设置随机数种子。

2、如何随机生成指定范围内的数字?如何生成指定精度的随机数?

假如问题要求生成1-10,2-55,99-998等范围内的随机数,我们如何来求解。由问题1,及rand函数的解释可知,rand()%100生成的是0-100,内的随机数不包括100,简记为[0,100),根据这样一个分析我们可以生成任意范围内的随机数:

 #include <iostream>
 #include <stdlib.h>
 #include <time.h>
 
 using namespace std;
 
 int main(){
	int i,temp;
	int low = 1;
	int high = 10;
	
	srand((unsigned)time(NULL)); //设置随机数种子
	
	for(i=0; i<10; i++){
		//rand()%(high-low)的范围是[0,high-low-1],加low,即为[low,high-1]≈[low,high)
		temp = rand()%(high-low)+low; 
		cout << temp << " ";
	}
	
	cout<<endl;
	return 0;
 }

结果:
C:\Users***\Desktop>g++ ranom.cpp

C:\Users***\Desktop>a.exe
6 5 4 3 8 1 4 2 2 7

C:\Users***\Desktop>a.exe
4 1 3 2 3 7 5 8 5 9

C:\Users***\Desktop>a.exe
7 3 2 1 4 1 3 5 2 8

以上是生成[low,high)范围内的随机数。

有时候我们需要随机生成小数,并保证指定精度,比如2位小数、3位小数等,如何设置呢?

 #include <iostream>
 #include <stdlib.h>
 #include <time.h>
 
 using namespace std;
 
 int main(){
	int i;
	double temp;
	
	srand((unsigned)time(NULL)); //设置随机数种子
	
	for(i=0; i<10; i++){		 
		temp = rand()%100 * 0.01;  //随机生成两位小数
		cout << temp << " ";
	}
	
	cout<<endl;
	return 0;
 }

C:\Users***\Desktop>g++ ranom.cpp

C:\Users***\Desktop>a.exe
0.16 0.93 0.53 0.58 0.49 0.89 0.96 0.81 0.48 0.29

C:\Users***\Desktop>a.exe
0.26 0.7 0.09 0.12 0.24 0.01 0.33 0.67 0.47 0.53

C:\Users***\Desktop>a.exe
0.29 0.51 0.05 0.07 0.39 0.28 0.46 0.4 0.58 0.05

如果要生成3位小数,只需要将100改为103,0.01改为0.13:

temp = rand()%1000 * 0.001;  //随机生成三位小数

3、如何随机生成若干不同的数字,并将其存在数组中?

rand生成的随机数是伪随机数,就是说有一定周期,生成若干个数字以后总会出现重复,但是一般情况下周期比较大,生成的数字足够使用。如何保证生成的数字都不相同呢?比如要生成5个8以内的随机数,见如下代码:

 #include <iostream>
 #include <stdlib.h>
 #include <time.h>
 #include <string.h>
 
 using namespace std; 
 
 int main(){
	int i,j,len = 5,index,stop;
	int temp,flag = 0,max = 8;
	int *arr = new int[len];
	memset(arr,-1,sizeof(int)*len);
	
	srand((unsigned)time(NULL)); //设置随机数种子
	
	index = 0; stop = 1;
	cout<<"All Num: ";
	while(stop){
		temp = rand()%max; //生成随机数
		cout<<temp << " ";
		flag = 0;
		for(j=0;j<index;j++)
		{
			if(arr[j] == temp){
				flag = 1;
			}
		}
		if(flag == 0)
		{
			arr[index ++] = temp;
			if(index == len )
				stop = 0;
		}
	}
	
	cout << endl << "Selected:";
	for(i=0; i<len; i++)
		cout<<arr[i]<<" ";
 
	return 0;
 } 

结果:
C:\Users*\Desktop>a.exe
All Num: 4 6 1 7 5
Selected:4 6 1 7 5
C:\Users*
\Desktop>a.exe
All Num: 3 7 2 5 2 4
Selected:3 7 2 5 4
C:\Users***\Desktop>a.exe
All Num: 1 0 2 4 7
Selected:1 0 2 4 7

结果中,第一行是生成的所有随机数,第二行是所选取的随机数。

对于随机数的使用,一定要注意随机种子的设定,同时还要自己动手测试,总结规律掌握技巧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值