二十四 随机函数 rand,srand,random,srandom 的区别与使用

来源:互联网 发布:做淘宝的流程 编辑:程序博客网 时间:2024/06/15 21:02
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
srandom((unsigned)time(NULL));// 不加这条代码,打印的10个数字不相同,但重新运行这个程序,打印的
// 的和上次的样。加上这条,打印的10个数,重新运行的都不一样。
int i ;
for(i=0;i<10;i++)
{
printf("%d\n",(random()%10)+1);
}

}


函数定义:

       int rand(void);                                         返回 0 ------- RAND_MAX 之间的一个 int 类型整数,该函数为非线程安全函数。并且生成随机数的性能不是很好,已经不推荐使用。
       void srand(unsigned int seed);          设置种子值,一般与“当前时间 进程ID”作为种子,如果没用调用该函数,则通过rand返回的默认种子值为1

 

官方推荐使用的函数为 :


long int random(void);    

返回 0 ------- RAND_MAX 之间的一个 long 类型整数,该函数会产生一个非常大的随机值,最大为 16*((2**31)-1)

random 函数使用非线性反馈随机数发生器生成默认大小为31个长整数表所返回的连续伪随机数。


 void srandom(unsigned int seed);      

设置种子值,一般与“当前时间 进程ID”作为种子,如果没用调用该函数,则通过random返回的默认种子值为1

 

 

使用方法 :

假如你想产生 1 ------10 之间的一个随机数, 你应该像下面这样编码

  j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));

 而不是下面这样的代码
   j = 1 + (rand() % 10);
结论:

如果你使用 srandom 种植种子, 则你应该使用 random 返回随机数, 如果你使用 srand 种植种子, 则你应该使用rand返回随机数。

不过srandrand官方已经不推荐使用。原因是产生随机数的性能不是很好, 另外是随机数的随机性没有random好, 再者就是不是线程安全

 

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main()

{

srandom((unsigned)time(NULL));// 不加这条代码,打印的10个数字不相同,但重新运行这个程序,打印的

// 的和上次的样。加上这条,打印的10个数,重新运行的都不一样。

int i ;

for(i=0;i<10;i++)

{

printf("%d\n",(random()%10)+1);

}

}

 

 

 

srand(time(NULL)); //是以当前时间为种子,产生随意数。其中,time(NULL)用来获取当前时间,本质上得到的是一个大整数,然后用这个数来随机数。

 

 

srand函数是随机数发生器的初始化函数。

  原型:void srand(unsigned seed);

  用法:它需要提供一个种子,这个种子会对应一个随机数,如果使用相同的种子后面的rand()函数会出现一样的随机数。如: srand(1); 直接使用1来初始化种子。不过为了防止随机数每次重复常常使用系统时间来初始化,即使用 time函数来获得系统时间,它的返回值为从 00:00:00 GMT, January 1, 1970 到现在所持续的秒数,然后将time_t型数据转化为(unsigned)型再传给srand函数,即: srand((unsigned) time(t)); 还有一个经常用法,不需要定义time_tt变量,即: srand((unsigned) time(NULL)); 直接传入一个空指针,因为你的程序中往往并不需要经过参数获得的t数据。srand((int)getpid()); 使用程序的ID(getpid())来作为初始化种子,在同一个程序中这个种子是固定的。

首先我们要对randsrand有个总体的看法:srand初始化随机种子,rand产生随机数,下面将详细说明。

rand(产生随机数)

表头文件: #include<stdlib.h>

定义函数 :int rand(void)

函数说明 :

因为rand的内部实现是用线性同余法做的,他不是真的随机数,只不过是因为其周期特别长,所以有一定的范围里可看成是随机的,rand()会返回一随机数值,范围在0RAND_MAX 间。在调用此函数产生随机数前,必须先利用srand()设好随机数种子,如果未设随机数种子,rand()在调用时会自动设随机数种子为1rand()产生的是假随机数字,每次执行时是相同的。若要不同,以不同的值来初始化它.初始化的函数就是srand()

返回值:

返回0RAND_MAX之间的随机整数值,RAND_MAX的范围最少是在32767之间(int),即双字节(16位数)。若用unsigned int 双字节是65535,四字节是4294967295的整数范围。

0~RAND_MAX每个数字被选中的机率是相同的。

范例:

/* 产生介于10 间的随机数值,此范例未设随机数种子,完整的随机数产生请参考

srand()*/

#include<stdlib.h>

main()

{

int i,j;

for(i=0;i<10;i++)

{

j=1+(int)(10.0*rand()/(RAND_MAX+1.0));

printf("%d ",j);

}

}

    执行:

 

9 4 8 8 10 2 4 8 3 6

9 4 8 8 10 2 4 8 3 6 //再次执行仍然产生相同的随机数

 

srand(设置随机数种子)

表头文件:#include<stdlib.h>

定义函数:void srand (unsigned int seed);

函数说明:

srand()用来设置rand()产生随机数时的随机数种子。参数seed必须是个整数,通常可以利用geypid()time(0)的返回值来当做seed。如果每次seed都设相同值,rand()所产生的随机数值每次就会一样。

范例

/* 产生介于10 间的随机数值,此范例与执行结果可与rand()参照*/

#include<time.h>

#include<stdlib.h>

main()

{

int i,j;

srand((int)time(0));

for(i=0;i<10;i++)

{

j=1+(int)(10.0*rand()/(RAND_MAX+1.0));

printf(" %d ",j);

}

}

      执行:与rand范例比较

 

5 8 8 8 10 2 10 8 9 9

2 9 7 4 10 3 2 10 8 7

又或:

"int x = rand() % 100;"来生成 到 100 之间的随机数这种方法是不或取的,比较好的做法是: j=(int)(*rand()/(RAND_MAX+1.0))产生一个0到n之间的随机数

int main(void)

{

    int i;

    time_t t;

    srand((unsigned) time(&t));

    printf("Ten random numbers from 0 to 99\n\n");

    for(i=0; i<10; i++)

        printf("%d\n", rand() % 100);

    return 0;

}

除以上所说的之外,补充一点就是srand这个函数一定要放在循环外面或者是循环调用的外面,否则的话得到的是相同的数字。

MSDN中的例子。

// crt_rand.c

// This program seeds the random-number generator

// with the time, then displays 10 random integers.

//

#include <stdlib.h>

#include <stdio.h>

#include <time.h>

int main( void )

{

    int i;

  

    // Seed the random-number generator with current time so that

    // the numbers will be different every time we run.

    //

    srand( (unsigned)time( NULL ) );

    // Display 10 numbers.

    for( i = 0;    i < 10;i++ )

       printf( "   %6d\n", rand() );

   printf("\n");

   // Usually, you will want to generate a number in a specific range,

   // such as 0 to 100, like this:

   {

      int RANGE_MIN = 0;

      int RANGE_MAX = 100;

      for (i = 0;     i < 10; i++ )

       {

          int rand100 = (((double) rand() /

                         (double) RAND_MAX) * RANGE_MAX + RANGE_MIN);

          printf( "   %6d\n", rand100);

       }

   }

总结:

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

初始化随机产生器既rand()函数的初始值,即使把种子的值改成a; 从这你可以看到通过sand()函数,我们是可以产生可以预见的随机序列,

那我们如何才能产生不可预见的随机序列呢?我们可能常常需要这样的随机序列,是吧。利用srand((unsign)(time(NULL))是一种方法,因为每一次运行程序的时间是不同的,对了,你知道time() 函数的功能是返回从1970/01/01到现在的秒数的吧,可能这个起始时间不正确,你查一下对不对吧,C还提供了另一个更方便的函数,randomize()

原形是void randomize(),功能是用来始初rand() 的种子的初始值,而且该值是不确定的,它相当于srand((unsign)(time(NULL)) 不过应注意的是randomize()的功能要通过time来实现所以在调用它时头文件要包含time.h罢了

为什么srand必须放在循环的外面,放在里面的话,每次srand的时候得到的种子都不一样,这样,不论执行多少次,永远不会得到两组相同的随机数 不是

 

我的观点错了,其实也是你没讲清楚,rand()一次以后,下一次的随机数种子就变成了上一次rand的返回值了



0 0