C++随机数的生成(1)

发布时间:2011-06-03 00:11:25

标准库(被包含于中)提供两个帮助生成伪随机数的函数:

函数一:int rand(void)
srand (seed)中指定的seed开始,返回一个[seed, RAND_MAX0x7fff)间的随机整数。

函数二:void srand(unsigned seed)
参数seedrand()的种子,用来初始化rand()的起始值。

可以认为rand()在每次被调用的时候,它会查看:
1 如果用户在此之前调用过srand(seed),给seed指定了一个值,那么它会自动调用
srand(seed)一次来初始化它的起始值。
2 如果用户在此之前没有调用过srand(seed),它会自动调用srand(1)一次。

根据上面的第一点我们可以得出:
1 如果希望rand()在每次程序运行时产生的值都不一样,必须给srand(seed)中的seed一个变值,这个变值必须在每次程序运行时都不一样(比如到目前为止流逝的时间)。
2 否则,如果给seed指定的是一个定值,那么每次程序运行时rand()产生的值都会一样,虽然这个值会是[seed, RAND_MAX0x7fff)之间的一个随机取得的值。
3 如果在调用rand()之前没有调用过srand(seed),效果将和调用了srand(1)再调用rand()一样(1也是一个定值)。

举几个例子,假设我们要取得06之间的随机整数(不含6本身):

例一,不指定seed
for(int i=0;i<10;i++){
ran_num=rand() % 6;
cout<
}
每次运行都将输出:5 5 4 4 5 4 0 0 4 2

例二,指定seed为定值1
srand(1);
for(int i=0;i<10;i++){
ran_num=rand() % 6;
cout<
}
每次运行都将输出:5 5 4 4 5 4 0 0 4 2
跟例子一的结果完全一样。

例三,指定seed为定值6
srand(6);
for(int i=0;i<10;i++){
ran_num=rand() % 6;
cout<
}
每次运行都将输出:4 1 5 1 4 3 4 4 2 2
随机值也是在[0,6)之间,随得的值跟srand(1)不同,但是每次运行的结果都相同。

例四,指定seed为当前系统流逝了的时间(单位为秒):time_t time(0)
#include
//
srand((unsigned)time(0));
for(int i=0;i<10;i++){
ran_num=rand() % 6;
cout<
}
第一次运行时输出:0 1 5 4 5 0 2 3 4 2
第二次:3 2 3 0 3 5 5 2 2 3
总之,每次运行结果将不一样,因为每次启动程序的时刻都不同(间隔须大于1秒?见下)。

关于time_t time(0)

time_t被定义为长整型,它返回从197011零时零分零秒到目前为止所经过的时间,单位为秒。比如假设输出:
cout<
值约为1169174701,约等于37(年)乘365(天)乘24(小时)乘3600(秒)(月日没算)。

另外,关于ran_num = rand() % 6

rand()的返回值与6求模是必须的,这样才能确保目的随机数落在[0,6)之间,否则rand()的返回值本身可能是很巨大的。
一个通用的公式是:
要取得[a,b)之间的随机整数,使用(rand() % (b-a)+ a (结果值将含a不含b)。
a0的情况下,简写为rand() % b

最后,关于伪随机浮点数:

rand() / double(RAND_MAX)可以取得01之间的浮点数(注意,不同于整型时候的公式,是除以,不是求模),举例:
double ran_numf=0.0;
srand((unsigned)time(0));
for(int i=0;i<10;i++){
ran_numf = rand() / (double)(RAND_MAX);
cout<
}
运行结果为:0.7166360.4577251001之间的浮点数,每次结果都不同。

如果想取更大范围的随机浮点数,比如110,可以将
rand() /(double)(RAND_MAX) 改为 rand() /(double)(RAND_MAX/10)
运行结果为:7.193626.4577510110之间的浮点数,每次结果都不同。
至于1001000的情况,如此类推。

C++中常用rand()函数生成随机数,但严格意义上来讲生成的只是伪随机数(pseudo-random integral number)。生成随机数时需要我们指定一个种子,如果在程序内循环,那么下一次生成随机数时调用上一次的结果作为种子。但如果分两次执行程序,那么由于种子相同,生成的随机数也是相同的。

在工程应用时,我们一般将系统当前时间(Unix时间)作为种子,这样生成的随机数更接近于实际意义上的随机数。给一下例程如下:

#include
#include
#include
using namespace std;

int main()
{
    double random(double,double);
    srand(unsigned(time(0)));
    for(int icnt = 0; icnt != 10; ++icnt)
        cout << "No." << icnt+1 << ": " << int(random(0,10))<< endl;
    return 0;
}

double random(double start, double end)
{
    return start+(end-start)*rand()/(RAND_MAX + 1.0);
}
/* 运行结果
* No.1: 3
* No.2: 9
* No.3: 0
* No.4: 9
* No.5: 5
* No.6: 6
* No.7: 9
* No.8: 2
* No.9: 9
* No.10: 6
*/
利用这种方法能不能得到完全意义上的随机数呢?似乎9有点多哦?却没有1,4,7?!我们来做一个概率实验,生成1000万个随机数,看0-910个数出现的频率是不是大致相同的。程序如下:
#include
#include
#include
#include
using namespace std;

int main()
{
    double random(double,double);
    int a[10] = {0};
    const int Gen_max = 10000000;
    srand(unsigned(time(0)));
   
    for(int icnt = 0; icnt != Gen_max; ++icnt)
        switch(int(random(0,10)))
        {
        case 0: a[0]++; break;
        case 1: a[1]++; break;
        case 2: a[2]++; break;
        case 3: a[3]++; break;
        case 4: a[4]++; break;
        case 5: a[5]++; break;
        case 6: a[6]++; break;
        case 7: a[7]++; break;
        case 8: a[8]++; break;
        case 9: a[9]++; break;
        default: cerr << "Error!" << endl; exit(-1);
        }
   
    for(int icnt = 0; icnt != 10; ++icnt)
        cout << icnt << ": " << setw(6) << setiosflags(ios::fixed) << setprecision(2) << double(a[icnt])/Gen_max*100 << "%" << endl;
   
    return 0;
}

double random(double start, double end)
{
    return start+(end-start)*rand()/(RAND_MAX + 1.0);
}
/* 运行结果
* 0: 10.01%
* 1:   9.99%
* 2:   9.99%
* 3:   9.99%
* 4:   9.98%
* 5: 10.01%
* 6: 10.02%
* 7: 10.01%
* 8: 10.01%
* 9:   9.99%
*/
可知用这种方法得到的随机数是满足统计规律的。

C语言产生随机数

C语言中,rand()函数可以用来产生随机数,但是这不是真真意义上的随机数,是一个伪随机数,是根据一个数,我们可以称它为种子,为基准以某个递推公式推算出来的一系数,当这系列数很大的时候,就符合正态公布,从而相当于产生了随机数,但这不是真正的随机数,当计算机正常开机后,这个种子的值是定了的,除非你破坏了系统,为了改变这个种子的值,C提供了srand()函数,它的原形是void srand( int a)

可能大家都知道C语言中的随机函数random,可是random函数并不是ANSI C标准,所以说,random函数不能在gcc,vc等编译器下编译通过。

rand()会返回一随机数值,范围在0RAND_MAX 间。返回0RAND_MAX之间的随机数值,RAND_MAX定义在stdlib.h(其值至少为32767)我运算的结果是一个不定的数,要看你定义的变量类型,int整形的话就是32767 在调用此函数产生随机数前,必须先利用srand()设好随机数种子,如果未设随机数种子,rand()在调用时会自动设随机数种子为1。一般用for语句来设置种子的个数。具体见下面的例子。

 

如何产生不可预见的随机序列呢
利用srand((unsigned int)(time(NULL))是一种方法,因为每一次运行程序的时间是不同的。

       C语言里所提供的随机数发生器的用法:现在的C编译器都提供了一个基于ANSI标准的伪随机数发生器函数,用来生成随机数。它们就是rand()srand()函数。这二个函数的工作过程如下:

1) 首先给srand()提供一个种子,它是一个unsigned int类型,其取值范围从0~65535

2) 然后调用rand(),它会根据提供给srand()的种子值返回一个随机数(032767之间)

3) 根据需要多次调用rand(),从而不间断地得到新的随机数;

4) 无论什么时候,都可以给srand()提供一个新的种子,从而进一步随机化”rand()的输出结果。
      下面是0~32767之间的随机数程序:

#include
#include
#include            //使用当前时钟做种子

void main( void )
{int i;
srand( (unsigned)time( NULL ) );          //初始化随机数
     for( i = 0; i < 10;i++ )                          //打印出10个随机数
          printf( " %d\n", rand() );
}

   根据上面的程序可以很容易得到0~1之间的随机数:

#include
#include
#include
main( )
{int i;
srand( (unsigned)time( NULL ) ); 
       for( i = 0; i < 10;i++ )
            printf( "%5.2f\n", rand()/32767.0);
}

     而产生1~100之间的随机数可以这样写:

#include
#include
#include
main( )
{int i;
srand( (unsigned)time( NULL ) ); 
       for( i = 0; i < 10;i++ )
            printf( "%d\n", rand()%100+1);
}
come from http://hi.baidu.com/akaneyu


二,三个通用的随机数发生器,推荐用第三个
函数名: rand
  : 随机数发生器
  : void rand(void);
程序例:

#include
#include

int main(void)
{
   int i;

   printf("Ten random numbers from 0 to 99\n\n");
   for(i=0; i<10; i++)
      printf("%d\n", rand() % 100);
   return 0;
}


  函数名: random
  : 随机数发生器
  : int random(int num);
程序例:

#include
#include
#include

/* prints a random number in the range 0 to 99 */
int main(void)
{
   randomize();
   printf("Random number in the 0-99 range: %d\n", random (100));
   return 0;
}
 
 

函数名: randomize     这个比较好!
  : 初始化随机数发生器
  : void randomize(void);
程序例:

#include
#include
#include

int main(void)
{
   int i;

   randomize();
   printf("Ten random numbers from 0 to 99\n\n");
   for(i=0; i<10; i++)
       printf("%d\n", rand() % 100);
   return 0;
}
 
在《计算机常用算法》中有介绍随机数的生成算法

如何产生设定范围内的随机数  

 由于rand产生的随机数从0rand_max,而rand_max是一个很大的数,那么如何产生从X~Y的数呢?

    XY,有YX1个数,所以要产生从XY的数,只需要这样写:

    k=rand()%(Y-X+1)+X;

    这样,就可以产生你想要的任何范围内的随机数了。

四,产生不重复的随机数
1 #include
#include
#include
 #include  
swap(int *pm,int *pn)      /*必须用指针进行交换*/
{
   int temp;
   temp=*pm;
   *pm=*pn;
   *pn=temp;
}

int main(void)
{
int   i,a[513];
/*int *pa,*pb;*/
srand( (unsigned)time( NULL ) ); /*定义这个可以产生不同的随机数*/
for(i=1;   i<=512;   i++){a[i]=i;printf("%4d",a[i]);}
for(i=512;   i>=1;   i--)
{
 /* pa=&a[i]; pb=&a[rand()%i+1];*/
  swap(&a[i], &a[rand()%i+1]);     /*加一是从一到i的随机,就不会包含0*/
  /*不用再定义指针,这样结论是一样的*/
}
   printf("\n")  ;
 for(i=1;   i<=64;   i++)
   printf("%4d",a[i] );
getch();   /*wintc的输出*/
}

2
 #include
#include
#include


int main(void)
{
   int a[100]={0};  int i,m;
    for(i=1;   i<=99;   ++i)
     printf("%4d",a[i] );

srand( (unsigned)time( NULL ) );

for(i=1; i<=99; i++)
{
        while(a[m=rand()%100+1]);
        a[m] = i;
}
       for(i=1;   i<=99;   ++i)
     printf("%4d",a[i] );

getch();
}

// Snake.cpp : 定义控制台应用程序的入口点。
//This program is used to collect the most mark and output the routine.
//by nwpu043814
//date:20100509

#include "stdafx.h"
#include
#include
#include

using namespace std;

//this struct represents an location.
typedef struct
{
int x;
int y;
} Pair;

class Grid
{
private :
Grid(const Grid& g);

public:
Pair * m_data;

const int m_width;     //grid width
const int m_height;   //grid height
int * m_adjacent;   //memory array

//constructor with width and height of the grid.
Grid(int x, int y):m_width(x), m_height(y)
{
   m_data = new Pair[x*y];
   memset(m_data, 0, x*y *sizeof(Pair));
   m_adjacent = new int[x*y];
   memset(m_adjacent, -1, x*y *sizeof(int));
}

//free resource
~Grid()
{
   delete [] m_data;
   delete [] m_adjacent;
}

int Bin2One(int x, int y)
{
   return y*m_width + x;
}

Pair One2Bin(int index)
{
   Pair p;
   p.x = index % m_width;
   p.y = index / m_width;
   return p;
}

//this method is used to get or set the item of the grid.
int & item(int x, int y)
{
   return m_data[x+ y*m_width].x;
}

//dynamic program main method, it recursively select the next location from the adjacents according to the priority.
int getCap(const Pair & loc)
{
   //this array is used to storage the priority of four adjacents.
   int value[4] = {0};

   //this array is used to access four adjacents according to current location.
   int mask[4][2] = {
    {-1,0},{0,1},{1,0},{0,-1}/*{x_coordinate, y_coordinate}*/
   };

   //now, we start to deal with four adjacents.
   for (int i = 0; i < 4; i++)
   {
    //make sure current location has four adjacents
    if (loc.x + mask[i][0] >= 0 && loc.x + mask[i][0] < m_width
     && loc.y + mask[i][1] >= 0 && loc.y + mask[i][1] < m_height)
    {
   
     //if the toy in the adjacent can hold current one.
     int current_toy = (m_data[Bin2One(loc.x, loc.y)].x > 0)?m_data[Bin2One(loc.x, loc.y)].x:m_data[Bin2One(loc.x, loc.y)].y;
     if ( item(loc.x + mask[i][0], loc.y + mask[i][1])   > current_toy//item(loc.x , loc.y)
      || item(loc.x + mask[i][0], loc.y + mask[i][1]) == 0)//when the adjacent has no toy.
     {
      Pair adjacent;
      adjacent.x = loc.x + mask[i][0];
      adjacent.y = loc.y + mask[i][1];

      m_data[Bin2One(adjacent.x, adjacent.y)].y = current_toy;
      value[i] = getCap(adjacent);
     }
    }  
   }

   int sum = 0;
   for (int i = 0; i < 4; i++)
   {
    sum += value[i];
   }

   //when all adjacents is less than current.
   if (sum == 0)
   {
    return item(loc.x , loc.y);
   }
   else
   {
   
    int index = 0;
    int current_max = value[index];
    int select = 0;

    for (int index = 0; index < 4; index++)
    {
     if (current_max < value[index])
     {
      current_max = value[index];
      select = index;
     }
    }
  
    m_adjacent[Bin2One(loc.x, loc.y)] = Bin2One(loc.x + mask[select][0], loc.y + mask[select][1]);

    return current_max + item(loc.x , loc.y);
   }
}

//this method drives the class
void run()
{
   Pair loc;
   loc.x = 0;
   loc.y = 0;

   for (int i = 0; i < m_width*m_height; i++)
   {
    m_data[i].y = m_data[i].x;
   }

   cout << "total mark=" << this->getCap(loc) << endl;
}

//display the grid
void displayGrid()
{
   for (int i =0 ; i < this->m_height; i++)
   {
    for (int j = 0; j < this->m_width; j++)
    {
     cout << " " << this->m_data[i*m_width + j].x;
    }
    cout << endl;
   }
}

//display the routine.
void print()
{
   int current, next, out ;
   current = 0;
   next = m_adjacent[current];
   out = m_data[current].x;
  
   while (next != -1)
   {
    cout << " " << out ;
    current = next;
    next = m_adjacent[current];
    out = m_data[current].x;
   }
   cout << " " << out ;
}


};


int _tmain(int argc, _TCHAR* argv[])
{
ifstream in("input.txt");
int x,y, k, value;

in >> x >> y ;

Grid * grid = new Grid(y, x);

value = 0;

//this block initializes the grid items with ifstream.
while (true)
{
    if (in.eof())
    {
     break;
    }
    in >> k;
   
    grid->item(value%grid->m_width, value/grid->m_width) = k;
    value++;
}

grid->displayGrid();
grid->run();//done
grid->print();

cin >>x;
delete grid;
grid = NULL;
in.close();
return 0;
}

// Snake.cpp : 定义控制台应用程序的入口点。
//This program is used to collect the most mark and output the routine.
//by nwpu043814
//date:20100509

#include "stdafx.h"
#include
#include
#include

using namespace std;

//this struct represents an location.
typedef struct
{
int x;
int y;
} Pair;

class Grid
{
private :
Grid(const Grid& g);

public:
Pair * m_data;

const int m_width;     //grid width
const int m_height;   //grid height
int * m_adjacent;   //memory array

//constructor with width and height of the grid.
Grid(int x, int y):m_width(x), m_height(y)
{
   m_data = new Pair[x*y];
   memset(m_data, 0, x*y *sizeof(Pair));
   m_adjacent = new int[x*y];
   memset(m_adjacent, -1, x*y *sizeof(int));
}

//free resource
~Grid()
{
   delete [] m_data;
   delete [] m_adjacent;
}

int Bin2One(int x, int y)
{
   return y*m_width + x;
}

Pair One2Bin(int index)
{
   Pair p;
   p.x = index % m_width;
   p.y = index / m_width;
   return p;
}

//this method is used to get or set the item of the grid.
int & item(int x, int y)
{
   return m_data[x+ y*m_width].x;
}

//dynamic program main method, it recursively select the next location from the adjacents according to the priority.
int getCap(const Pair & loc)
{
   //this array is used to storage the priority of four adjacents.
   int value[4] = {0};

   //this array is used to access four adjacents according to current location.
   int mask[4][2] = {
    {-1,0},{0,1},{1,0},{0,-1}/*{x_coordinate, y_coordinate}*/
   };

   //now, we start to deal with four adjacents.
   for (int i = 0; i < 4; i++)
   {
    //make sure current location has four adjacents
    if (loc.x + mask[i][0] >= 0 && loc.x + mask[i][0] < m_width
     && loc.y + mask[i][1] >= 0 && loc.y + mask[i][1] < m_height)
    {
   
     //if the toy in the adjacent can hold current one.
     int current_toy = (m_data[Bin2One(loc.x, loc.y)].x > 0)?m_data[Bin2One(loc.x, loc.y)].x:m_data[Bin2One(loc.x, loc.y)].y;
     if ( item(loc.x + mask[i][0], loc.y + mask[i][1])   > current_toy//item(loc.x , loc.y)
      || item(loc.x + mask[i][0], loc.y + mask[i][1]) == 0)//when the adjacent has no toy.
     {
      Pair adjacent;
      adjacent.x = loc.x + mask[i][0];
      adjacent.y = loc.y + mask[i][1];

      m_data[Bin2One(adjacent.x, adjacent.y)].y = current_toy;
      value[i] = getCap(adjacent);
     }
    }  
   }

   int sum = 0;
   for (int i = 0; i < 4; i++)
   {
    sum += value[i];
   }

   //when all adjacents is less than current.
   if (sum == 0)
   {
    return item(loc.x , loc.y);
   }
   else
   {
   
    int index = 0;
    int current_max = value[index];
    int select = 0;

    for (int index = 0; index < 4; index++)
    {
     if (current_max < value[index])
     {
      current_max = value[index];
      select = index;
     }
    }
  
    m_adjacent[Bin2One(loc.x, loc.y)] = Bin2One(loc.x + mask[select][0], loc.y + mask[select][1]);

    return current_max + item(loc.x , loc.y);
   }
}

//this method drives the class
void run()
{
   Pair loc;
   loc.x = 0;
   loc.y = 0;

   for (int i = 0; i < m_width*m_height; i++)
   {
    m_data[i].y = m_data[i].x;
   }

   cout << "total mark=" << this->getCap(loc) << endl;
}

//display the grid
void displayGrid()
{
   for (int i =0 ; i < this->m_height; i++)
   {
    for (int j = 0; j < this->m_width; j++)
    {
     cout << " " << this->m_data[i*m_width + j].x;
    }
    cout << endl;
   }
}

//display the routine.
void print()
{
   int current, next, out ;
   current = 0;
   next = m_adjacent[current];
   out = m_data[current].x;
  
   while (next != -1)
   {
    cout << " " << out ;
    current = next;
    next = m_adjacent[current];
    out = m_data[current].x;
   }
   cout << " " << out ;
}


};


int _tmain(int argc, _TCHAR* argv[])
{
ifstream in("input.txt");
int x,y, k, value;

in >> x >> y ;

Grid * grid = new Grid(y, x);

value = 0;

//this block initializes the grid items with ifstream.
while (true)
{
    if (in.eof())
    {
     break;
    }
    in >> k;
   
    grid->item(value%grid->m_width, value/grid->m_width) = k;
    value++;
}

grid->displayGrid();
grid->run();//done
grid->print();

cin >>x;
delete grid;
grid = NULL;
in.close();
return 0;
}

应百度网友wu329613403的要求,花半小时写了个大体思路,最近太忙了,只能写个思路,估计有不完善的地方,欢迎指正。(注意题目中没有给将距离与时间沟通起来的教师行进速度,我认为应该给。)

A,假设家长数目为N,从文件读取家长的时间表,定义一个家长类,包括的成员为开始时间,结束时间,家长编号,存储到其余每个家长的距离的一个数组,从文件读入多少个家长就创建多少个家长对象,用一个容器C1来存放N个家长对象的指针,定义一个容器C2保存家长的拜访情况.
B,删除安排时间段小于45分钟的家长,根据每个家长的开始时间对容器C1中的家长进行排序,时间早的排在最前面。
C,选取开始时间最早的家长作为当前准备拜访的家长,拜访时间持续45分钟,将当前家长的拜访情况保存到容器C2,同时从容器C1中删除当前家长的信息。
D,用当前家长到其余每个(未拜访)的家长的时间加上各个家长的开始时间作为每个家长的新的开始时间,重新对容器C1按照新的开始时间进行排序,对容器中的家长C1[i]进行判断(i0开始)
   if(当前家长的开始时间比现在的时间早(小,意思是已经错过了))
{
  
   新拜访结束时刻1 = 当前时时刻+ 刚刚拜访的家长到当前家长C1[i]需要的时间长度 + 45分钟;
   if (新拜访结束时刻1 家长C1[i]的结束时刻早(或者为同一个时刻))
   {
    拜访这个家长C1[i],时间持续45分钟;
    将拜访信息添加到C2;
    C1中删除当前家长C1[i];
   
    if(C1不为空)
    {
     goto D;(意思是:重复步骤D的内容)
    }
    else
    {
     goto E;(去输出C2的内容)
    }
   }
   else
   {
    C1中删除当前家长C1[i];
   }

}
else
{
   拜访容器C1中的排第一的家长,时间持续45分钟;(出现这种情况,就是老师走到下个拜访的家长的时候,拜访时间还没有开始,需要等待一段时间,实际上这样的情况是浪费了时间了,谁叫这个家长的开始时间安排的晚呢,不能怪老师。)
   将拜访信息添加到C2;
   C1中删除当前家长C1[i];
   
   if(C1不为空)
   {
    goto D;(意思是:重复步骤D的内容)
   }
   else
   {
    goto E;(去输出C2的内容)
   }
}
E,根据容器C2的拜访记录输出家访安排计划。

C++随机数的生成(1)

相关推荐