C++产生不重复的随机数
2015-09-03 22:27
211 查看
在编写考试题目时,要求在一定范围内随机出题,但是如果按如下的方法设计程序:
void shuiji(int min,int max)//从min到max范围内随机出题
{
int num=max-min+1; //比如15到20,实际上是6个,因此要加1
int i;
for(i=0;i<num;i++)
{
a[ i ]=min+rand()%(num);//每产生一个min到max的数就用数组a[ i ]保存起来
};//a[ i ]就是要出题的标号了
}
产生的题目标号会重复。并且因为每次都要随机运算,时间也用得长一些。
怎么让它短时间内就能产生不重复的随机数呢?
可以用如下的方法进行解决:
1、把你要随机的数,放在一个数组中。
2、然后用rand()产生一个随机的数组下标与它对应。但是这个随机下标还是会产生重复, 如何解决呢?
3: 用随机产生的 最大下标减1的数组所对应的值 来替换己被取出的下标数组中的值。 也就是第2步是读取,3步是读完后就扔掉。读了的数被扔掉后,后面的数就不会产生重复了。:)
4: goto 2
比如,要被随机的数的顺序是15,16,17,18,19,20 它们被放在a[ i ]数组中,然后产生一个随机下标:
i=0时 比如随机下标index的值是 1
读取第一个数:a[1], 保存在j[ i ]中,此例的数是15(这就是我们要的随机数呢)。
a[1]的值15读取后,15不会再被用了,否则会有产生重复的危险
因此,15应该丢掉,用别的代替。用哪一个代替呢?用最大下标减1再减当前下标代替。
此例中的15被 a[ num-1-i ]=a[6-1-0]=20代替了,现在要被随机的数就变成了:
20,16,17,18,19,20
i=1时 比如随机下标index的值是 0
读取第0个数:a[ index ], 保存在j[ i ]中,此例的数是20(这就是我们要的随机数呢)。
a[ index ]被a[ num-1-i ]=a[6-1-1]=a[4]=19 代替。
现在要被随机的数就变成了:
20,19,17,18,19,20
注意:现在己经取出了2个随机数了呢:即15,19 它们己经被放在j数组中了。
......下面的自己分析
我写了一个函数,如下
void shuiji(int min,int max)
{
int num=max-min+1; //要随机数的个数
int index; //随机下标
for(int i=0;i<num;i++) //准备要被随机的数
a[ i ]=i+min;
srand((int)time(0)); //随机种子
for(int i=0;i<num;i++)
{
index=(int)((float)(num-i)*rand()/(RAND_MAX+1.0)); //产生随机下标
j[ i ]=a[index]; //把不重复的随机数下标保存到数组中
a[ index ]=a[ num-1-i ]; //用随机范围内的最后一个随机下标对应的值,去替换己用过的值.这样就不重复了.(即
//把上面用过的a[ index ]丢掉。)
};
}
在程序中的具体用法如下:
#include <ionstream>
#include<stdlib.h> //要加
#include <time.h> //一定要加上,不然后面的srand((int)time(0))不能用
using namespace std;
int a[50],j[50]; //不知道你取的数组是多大,这里用50个吧
int main()
{
void shuiji(int ,int );
shuiji(20,35);
for(int i=0;i<35-20+1;i++)
cout<<j[ i ]; //j数组就是不重复的随机数了
getchar(); //此句是用来程序暂停的
}
void shuiji(int min,int max)
{
int num=max-min+1; //要随机数的个数
int index; //随机下标
for(int i=0;i<num;i++) //准备要被随机的数
a[ i ]=i+min;
srand((int)time(0)); //随机种子
for(int i=0;i<num;i++)
{
index=(int)((float)(num-i)*rand()/(RAND_MAX+1.0)); //产生随机下标
j=a[index]; //把不重复的随机数下标保存到数组中
a[ index ]=a[ num-1-i ]; //用随机范围内的最后一个随机下标对应的值,去替换己用过的值.这样就不重复了.(即把上面用过的a[index]丢掉。)
};
}
//+++++++++++++++++++++++
补充资料:
rand()通常的使用方法是这样的:
rand()不需要参数,它会返回一个从0到最大随机数的任意整数,最大随机数的大小通常是固定的一个大整数。 这样,如果你要产生0~10的10个整数,可以表达为:
int N = rand() % 11;
这样,N的值就是一个0~10的随机数,如果要产生1~10,则是这样:
int N = 1 + rand() % 11;
总结来说,可以表示为:
int n=min+rand()%(max-min+1);
其中的min是起始值,n是整数的范围。
若要0~1的小数,则可以先取得0~10的整数,然后均除以10即可得到随机到十分位的10个随机小数,若要得到随机到百分位的随机小数,则需要先得到0~100的10个整数,然后均除以100,其它情况依此类推。
通常rand()产生的随机数在每次运行的时候都是与上一次相同的,这是有意这样设计的,是为了便于程序的调试。若要产生每次不同的随机数,可以使用srand( seed )函数进行随机化,随着seed的不同,就能够产生不同的随机数。
如大家所说,还可以包含time.h头文件,然后使用srand( time(0))来使用当前时间使随机数发生器随机化,这样就可以保证每两次运行时可以得到不同的随机数序列(只要两次运行的间隔超过1秒)。 为最大值,其随机域为0~MAX-1
具体的C++随机程序如下:
#include <iostream>
#include <time.h>
#include
using namespace std;
int main(int argc, char* argv[])
{
srand( (unsigned)time( NULL ) ); //srand()函数产生一个以当前时间开始的随机种子
for (int i=0;i<10;i++)
cout<<rand() % 11;
}
void shuiji(int min,int max)//从min到max范围内随机出题
{
int num=max-min+1; //比如15到20,实际上是6个,因此要加1
int i;
for(i=0;i<num;i++)
{
a[ i ]=min+rand()%(num);//每产生一个min到max的数就用数组a[ i ]保存起来
};//a[ i ]就是要出题的标号了
}
产生的题目标号会重复。并且因为每次都要随机运算,时间也用得长一些。
怎么让它短时间内就能产生不重复的随机数呢?
可以用如下的方法进行解决:
1、把你要随机的数,放在一个数组中。
2、然后用rand()产生一个随机的数组下标与它对应。但是这个随机下标还是会产生重复, 如何解决呢?
3: 用随机产生的 最大下标减1的数组所对应的值 来替换己被取出的下标数组中的值。 也就是第2步是读取,3步是读完后就扔掉。读了的数被扔掉后,后面的数就不会产生重复了。:)
4: goto 2
比如,要被随机的数的顺序是15,16,17,18,19,20 它们被放在a[ i ]数组中,然后产生一个随机下标:
i=0时 比如随机下标index的值是 1
读取第一个数:a[1], 保存在j[ i ]中,此例的数是15(这就是我们要的随机数呢)。
a[1]的值15读取后,15不会再被用了,否则会有产生重复的危险
因此,15应该丢掉,用别的代替。用哪一个代替呢?用最大下标减1再减当前下标代替。
此例中的15被 a[ num-1-i ]=a[6-1-0]=20代替了,现在要被随机的数就变成了:
20,16,17,18,19,20
i=1时 比如随机下标index的值是 0
读取第0个数:a[ index ], 保存在j[ i ]中,此例的数是20(这就是我们要的随机数呢)。
a[ index ]被a[ num-1-i ]=a[6-1-1]=a[4]=19 代替。
现在要被随机的数就变成了:
20,19,17,18,19,20
注意:现在己经取出了2个随机数了呢:即15,19 它们己经被放在j数组中了。
......下面的自己分析
我写了一个函数,如下
void shuiji(int min,int max)
{
int num=max-min+1; //要随机数的个数
int index; //随机下标
for(int i=0;i<num;i++) //准备要被随机的数
a[ i ]=i+min;
srand((int)time(0)); //随机种子
for(int i=0;i<num;i++)
{
index=(int)((float)(num-i)*rand()/(RAND_MAX+1.0)); //产生随机下标
j[ i ]=a[index]; //把不重复的随机数下标保存到数组中
a[ index ]=a[ num-1-i ]; //用随机范围内的最后一个随机下标对应的值,去替换己用过的值.这样就不重复了.(即
//把上面用过的a[ index ]丢掉。)
};
}
在程序中的具体用法如下:
#include <ionstream>
#include<stdlib.h> //要加
#include <time.h> //一定要加上,不然后面的srand((int)time(0))不能用
using namespace std;
int a[50],j[50]; //不知道你取的数组是多大,这里用50个吧
int main()
{
void shuiji(int ,int );
shuiji(20,35);
for(int i=0;i<35-20+1;i++)
cout<<j[ i ]; //j数组就是不重复的随机数了
getchar(); //此句是用来程序暂停的
}
void shuiji(int min,int max)
{
int num=max-min+1; //要随机数的个数
int index; //随机下标
for(int i=0;i<num;i++) //准备要被随机的数
a[ i ]=i+min;
srand((int)time(0)); //随机种子
for(int i=0;i<num;i++)
{
index=(int)((float)(num-i)*rand()/(RAND_MAX+1.0)); //产生随机下标
j=a[index]; //把不重复的随机数下标保存到数组中
a[ index ]=a[ num-1-i ]; //用随机范围内的最后一个随机下标对应的值,去替换己用过的值.这样就不重复了.(即把上面用过的a[index]丢掉。)
};
}
//+++++++++++++++++++++++
补充资料:
rand()通常的使用方法是这样的:
rand()不需要参数,它会返回一个从0到最大随机数的任意整数,最大随机数的大小通常是固定的一个大整数。 这样,如果你要产生0~10的10个整数,可以表达为:
int N = rand() % 11;
这样,N的值就是一个0~10的随机数,如果要产生1~10,则是这样:
int N = 1 + rand() % 11;
总结来说,可以表示为:
int n=min+rand()%(max-min+1);
其中的min是起始值,n是整数的范围。
若要0~1的小数,则可以先取得0~10的整数,然后均除以10即可得到随机到十分位的10个随机小数,若要得到随机到百分位的随机小数,则需要先得到0~100的10个整数,然后均除以100,其它情况依此类推。
通常rand()产生的随机数在每次运行的时候都是与上一次相同的,这是有意这样设计的,是为了便于程序的调试。若要产生每次不同的随机数,可以使用srand( seed )函数进行随机化,随着seed的不同,就能够产生不同的随机数。
如大家所说,还可以包含time.h头文件,然后使用srand( time(0))来使用当前时间使随机数发生器随机化,这样就可以保证每两次运行时可以得到不同的随机数序列(只要两次运行的间隔超过1秒)。 为最大值,其随机域为0~MAX-1
具体的C++随机程序如下:
#include <iostream>
#include <time.h>
#include
using namespace std;
int main(int argc, char* argv[])
{
srand( (unsigned)time( NULL ) ); //srand()函数产生一个以当前时间开始的随机种子
for (int i=0;i<10;i++)
cout<<rand() % 11;
}
相关文章推荐
- 高性能Tomcat:漫谈行走在sendfile之上的Tomcat
- 访问google的一些方法
- HDU 2896-病毒侵袭(ac自动机)
- 统计信息
- 1553 时钟
- 大数据——海量数据处理的基本方法总结
- 文件系统上的特殊权限
- android-------采用AIDL调用远程服务
- Swift 学习笔记 4-函数
- 【Python基础】Python面向对象 - 3 - 新类,静态方法,类方法,实例方法
- PE文件详解之块表
- FreeSWITCH - mod_xml_rpc源码分析三chanswitch.c
- LINUX系统中动态链接库的创建与使用{补充}
- LINUX系统中动态链接库的创建与使用
- Nosql技术--redis系列--redis的数据类型 及相应的命令--String类型
- linux svn启动和关闭(转)
- 存储过程
- 2015款 mac下利用U盘装Win8系统
- Oracle 多行转多列
- makefile 自动处理头文件的依赖关系 (zz)