生成随机数据
生成随机数据
一.生成int型数据
- 简单地生成n个随机数据(数字大小在int范围内)
#include <cstdio>
#include <cstdlib>
#include <cmath>
int main()
{
int n=60;
for(int i=1; i<=n; i++)
printf("%d ",rand());
printf("\n");
return 0;
}
每次运行该程序得到的随机数都是一样的,因为种子相同
- 改变种子,每次运行程序可以得到不同的随机数
得到种子需要一个函数srand(m); 参数m决定了种子,那么每次运行的时候我们需要改变m以便得到不同的种子,显然很麻烦,所以我们可以自动生成种子,就是使用一个time()函数,以当前时间来作为种子
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
int main()
{
int n=60;
srand((int)time(0));
for(int i=1; i<=n; i++)
printf("%d ",rand());
printf("\n");
return 0;
}
- 生成范围在[a,b]以内的随机数据
先说简单的,如果是要生成[0,b]以内的数据那么只要对b+1取模即可
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
int main()
{
int n=60,b=100;
srand((int)time(0));
for(int i=1; i<=n; i++)
printf("%d ",rand()%(b+1));
printf("\n");
return 0;
}
如果是[a,b]类型的(即a不为0),有多种处理方法,这里只提供一种方法,就是多次取随机数直到满足要求为止,当然也可以用其他方法最常见就是用数学处理
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
int main()
{
int n=60,a=50,b=100;
srand((int)time(0));
for(int i=1; i<=n; i++)
{
int t=rand()%(b+1);
if(t>=a && t<=b)
printf("%d ",t);
else
{
do
{ t=rand()%(b+1); }
while(!(t>=a && t<=b));
printf("%d ",t);
}
}
printf("\n");
return 0;
}
- 不重复生成随机数据
上面的程序中都可以看到数据中经常出现重复的情况,为了解决重复的问题可以采用标记的方法
一种是,把需要用到的数据事先保存在一个数组中(某些情况下我们是确定知道我们需要用到哪些数据(例如我们需要[0,10000]里面的数字),只是对于它们的出现顺序我们希望得到一个随机的结果,并且每个数据只出现一次),然后随机生成数据r,r并不是我们要的数据,而是数组下标,我们需要的是事先保存下来的a[r],并且标记used[r]=1,表示下标r的数据已经用过,所以对于已经用过的数据我们不能再次使用,必须重新计算得到一个新的随机数字r,或者使用其他方法得到一个没有用过的r
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#define N 100010
int num[N],used[N];
int main()
{
int n=40,b=0;
for(int i=1; i<=100; i+=2,b++)
{ num[b]=i; used[b]=0; }
//将[0,100]以内的奇数先事先保存在num数组中
//随机输出num数组里面的数据每个数据仅输出一次
//(也就是输出100以内的奇数每个只输出一次)
srand((int)time(0));
for(int i=0; i<b; i++)
{
int r=rand()%b;
if(!used[r])
{ used[r]=1; printf("%d ",num[r]); }
else
{
do
{ r=rand()%b; }
while(used[r]);
used[r]=1; printf("%d ",num[r]);
}
}
printf("\n");
return 0;
}
二.生成浮点型数据
一个不太严谨的方法是直接
小于1的浮点数,rand() /(double)RAND_MAX;
0~10的浮点数,则修改为rand() /(double)(RAND_MAX/10);
0~100浮点数,则修改为rand() /(double)(RAND_MAX/100)
......以此类推
其中RAND_MAX是一个数值,windows系统下一般为32767,rand()的数值范围在RAND_MAX以内
还有一种方法是,先随机出一个整数,再随机出一个小数,然后两个数相加
还有一个方法是每次随机得到个位数然后不断作为个位,十位,百位,千位……这样就构建好了整数部分,然后再用相同的方法来构建小数部分,整数部分加上小数部分就得到了我们要的随机数
三.生成字符型数据
字符型数据我们可以转化为ASCII码来处理,以下面的例子来说明
我们需要生成20个字符串,每个字符串占1行。对于每个字符串,长度范围在[1,10],每个字符串可以包含的字符包括0到9,26个大小写字母,也就是只可能出现62种不同的字符
解决方法,我们先将62个字符保存在一个字符数组string中,然后我们随机生成一个数字len,表示当前字符串的长度(记得取模保证len在[1,10]范围内),然后循环len次,每次生成一个字符。生成字符的方法是,随机生成一个数字r,然后读取string[r]里面的单个字符。
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#define N 110
char string[N]={"012345679ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"};
int main()
{
int n=20,len;
srand((int)time(0));
for(int i=1; i<=n; i++) //生成n个字符串
{
do
{len=rand()%(10+1);} //得到当前字符串的长度
while(!(len>0));
for(int j=1; j<=len; j++)
printf("%c",string[rand()%(62)]);
printf("\n");
}
return 0;
}
当然我们可以直接生成一个随机数字r(记得模256+1),然后读取ASCII码为r的字符,但是这种方法不推荐