随机数

来源:互联网 发布:藏文字体软件下载 编辑:程序博客网 时间:2024/04/25 02:04
生成四位没有重复数字位的随机数
/* *****************************************
   ** @Author : Emil
   ** @Version : 1.0
   ** @Intro : create 4 digit random number with no duplicated digit
** ************************************** */
#include<iostream>
#include<ctime>  
#include<cassert>
using namespace std;
unsigned int myrand(const unsigned int, const unsigned int);  //生成指定范围内的随机数
unsigned int myRand();  //生成四位无重复数字位的随机数
int main()
{
    /*生成指定范围内的随机数
   unsigned int min, max;
    cout<<"please input the min No.(between 0~65535): ";
    cin>>min;
    cout<<"please input the max No.(between 0~65535): ";
    cin>>max;
    cout<<"the rand number between "<<min<<" and "<<max<<" is: "<<myrand(min,max)<<'/n';
    */
   
    cout<<"rand 4 digit number with no duplicated digit: "<<myRand()<<'/n';
    system("pause");
}
unsigned int myrand(const unsigned int min, const unsigned int max)
{
    assert(max>=min);
    srand(unsigned(time(NULL)));
    return (rand()%(max-min+1)+min);   //关键算法 rand()%(max-min+1)+min即得到[min,max]区间内的随机数
}
unsigned int myRand()//const unsigned int min, const unsigned int max)
{
    unsigned int r;
    bool flag=false;      //标志位,重复则设为true
   
    srand(unsigned(time(NULL)));
    do{
       flag=false;
       r = rand()%(9999-1000+1)+1000;
      
       //获得随机数的各位数字
       unsigned int a = r/1000;                
       unsigned int b = (r-a*1000)/100;
       unsigned int c = (r-a*1000-b*100)/10;
       unsigned int d = r-a*1000-b*100-c*10;
      
       if(a == b||a == c||a == d||b == c||b == d||c == d)  //若有重复,flag置true,重新生成
            flag = true;
    }
    while(flag);
   
    return r;
}

 
参考了onlinewan的实现,如下:
C++实现生成随机数

/* *****************************************
   ** @Author : onlinewan
   ** @Version : 1.0
   ** @Intro : create random number
** ************************************** */
//生成随机数

#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

unsigned int createRandomNum (unsigned int min, unsigned int max);

int main ()
{
    int min,max;
    cout << "Enter mininum and maxinum: ";
    cin>>min>>max;
    int randNum = createRandomNum(min,max);
    cout << "Create a random number is : " << randNum <<"/n";
 
    cin.get();
    cin.get();
    return 0;
}

unsigned int createRandomNum (unsigned int min, unsigned int max)
{//产生指定范围内的随机数 应包含头文件:ctime(time.h),cstdlib(stdlib.h)
         unsigned int seed = time(0);
         srand(seed);  //srand(unsigned int)用来初始化种子
         unsigned int randNum = rand() /100%(max - min + 1) + min;
         return randNum;        
}

 


知其然亦知其所以然,让我们来求甚解一下吧

 

显然要从其中的关键函数是怎么起作用的来着手了,我们来看看msdn的介绍先:

srand() 如下:


 

Sets a random starting point.

void srand(   unsigned int seed );

Parameters

seed
Seed for random-number generation

Remarks

The srand function sets the starting point for generating a series of pseudorandom integers. To reinitialize the generator, use 1 as the seed argument. Any other value for seed sets the generator to a random starting point. rand retrieves the pseudorandom numbers that are generated. Calling rand before any call to srand generates the same sequence as calling srand with seed passed as 1.

Requirements

Routine Required header Compatibility srand <stdlib.h> ANSI, Win 98, Win Me, Win NT, Win 2000, Win XP

 


 

E文是这样解释的:srand(unsigned int seed)会利用它的seed参数作为起始点生成一个伪随机的整数序列,随后就可用rand()函数取出生成的随机数了。值得注意的是,不使用srand()而直接使用rand()函数和用srand(1)设置种子的效果一样,rand()将会返回任何时候都一样的非随机数,这显然是我们不想看到的。

1) 首先给srand()提供一个种子,它是一个unsigned int类型,其取值范围从0~65535;
2) 然后调用rand(),它会根据提供给srand()的种子值返回一个随机数(在0到32767之间)

再来看看srand()和rand()函数最基本的内部实现(这是未经过优化的版本,stdlib.h中的rand返回值的上限是一个常量RAND_MAX-32767):

<<The C++ Programming Language>>(随机数生成的基本方法)
int randx = 0;
int rand()
{
randx = randx * 1103515245 + 12345;
return randx;
}
void srand(int a)
{
randx = a;
}

 


 

补充:

各种编程语言返回的随机数(确切地说是伪随机数)实际上都是根据递推公式计算的一组数值,当序列足够长,这组数值近似满足均匀分布。如果计算伪随机序列的初始数值(称为种子)相同,则计算出来的伪随机序列就是完全相同的。这个特性被有的软件利用于加密和解密。加密时,可以用某个种子数生成一个伪随机序列并对数据进行处理;解密时,再利用种子数生成一个伪随机序列并对加密数据进行还原。这样,对于不知道种子数的人要想解密就需要多费些事了。当然,这种完全相同的序列对于你来说是非常糟糕的。要解决这个问题,需要在每次产生随机序列前,先指定不同的种子,这样计算出来的随机序列就不会完全相同了。你可以在调用rand()函数之前调用srand( (unsigned)time( NULL ) ),这样以time函数值(即当前时间)作为种子数,因为两次调用rand函数的时间通常是不同的,这样就可以保证随机性了。

于是下面例子就有错了:

#include <stdlib.h>
    #include <iostream.h>
    #include <conio.h>
    #include <time.h>
    void main()
    {
     for(int i=0;i<100000;i++)
     {
     srand( (unsigned)time( NULL ) );
     cout<<rand()<<endl;
     }
    }
    答:程序是有问题的,每产生一个随机数之前,都调用一次srand,而由于计算机运行很快,所以你每次用time得到的时间都是一样的(time的时间精度较低,只有55ms)。这样相当于使用同一个种子产生随机序列,所以产生的随机数总是相同的。应该把srand放在循环外:
     srand( (unsigned)time( NULL ) );
    
for(int i=0;i<100000;i++)
    
{
    
cout&lt;&lt;rand()&lt;&lt;endl;
    
}

也就是说,使用rand()还要注意,srand()要保证不一样才能生成不同的随机数,由于将time(NULL)作为seed,所以必需要和上次调用间隔差不多一秒之后再次调用才能有效得到随机数。

 利用毫秒降低限制


 

 

引两篇文章,感谢两位原创:

 真正的随机数的探讨

较详细的随机数探究


若要生成大量随机数,而且没有重复(eg.不能有两个1234),可以用到STL中的set,如下

TreeSet temp = new TreeSet();

TreeSet在add(Object)的时候是自动判断是否重复的,如果加入的对象已经在该Set中已经存在,则返回一个false,加不进去~这样就省去判断是否重复了~

 


先到这里,各位看官,若有帮助,本人欣慰之极;若觉简单,呲之以鼻,权且见笑。