用C语言的rand()和srand()产生伪随机数的方法总结
- 格式:docx
- 大小:15.42 KB
- 文档页数:3
浅析C语⾔中的rand函数和srand函数(⼀)我们在编程实现算法的过程中,往往需要使⽤到随机数。
由于计算机是⼀台以逻辑为基础的机器,没法做到真正的随机(⼤概量⼦计算机可以?)。
所以计算机⽣成的是伪随机数,供我们使⽤。
我们使⽤C语⾔的rand函数,⽣成的也是伪随机数。
⼀个简单的⽰范如下:1 #include <stdio.h>2 #include <stdlib.h>3 #include <time.h>45int6 main(int argc, char** argv)7 {8// 以机器当前的时间来构造⽣成伪随机数的"种⼦" 。
9 srand((unsigned int)time(NULL));10int i;11// 打印10个伪随机数12for (i = 0; i < 10; i++) {1314 printf("%d ", rand());15 }16 printf("\n");1718 system("pause");19return0;20 }很显然,如果不使⽤第九⾏的srand函数,那么我们的程序每次打印的10个伪随机数序列是⼀样的,在本机上始终是41, 18467, 6334, ......。
这是由于C语⾔是利⽤linear congruential generator作为⽣成器来⽣成伪随机数,但是这个⽣成器⽣成伪随机数,需要⼀个“种⼦”来进⾏运算。
⽽如果我们仅仅调⽤rand函数,那么我们始终使⽤的是C语⾔⾃⼰设置的固定的“种⼦”来⽣成伪随机数,所以⽣成的伪随机数的序列肯定是⼀模⼀样的咯。
当我们使⽤srand,以时间为参数,为rand提供⼀个不⼀样的“种⼦”,那么由于每次的“种⼦”都不⼀样,当然每次的伪随机数的序列都不⼀样。
但是从代码实现中,我们不能清楚地看出来srand函数提供的“种⼦”如何就被rand函数⽤上了。
有关rand(),srand()产⽣随机数学习总结要计算机产⽣⼀个随机数不像扔⾊⼦⼀样,计算机的每⼀步操作,就是执⾏⼀堆代码,这些代码是事先安排好的,所以计算机的产⽣⾏为是不具有随机性和预测性的(当然这⾥说的是现阶段的计算机体系,到未来的计算机的体系,未知),所以计算机产⽣的随机数都不是真正意义上的随机数,只是伪随机数,他以⼀个真值(也称为种⼦)作为初始条件,然后⽤⼀定的算法不停迭代产⽣随机数。
库函数中系统提供了两个函数⽤于产⽣随机数:srand()和rand();rand函数:头⽂件<stdlib.h>定义函数:int rand(void),函数功能:产⽣随机数,函数说明:因为rand的内部是⽤线性同余法做的,不是真的随机数,只不过因为其周期特别长,所以在⼀定范围内可以看成是随机的,rand()会返回⼀随机值,范围在0到RAND_MAX间,在调⽤此函数产⽣随机数前,必须利⽤srand()设好随机数种⼦,若没有设随机数种⼦,rand()在调⽤时会⾃动设随机数种⼦为1。
返回值:返回0到RAND_MAX之间的整数值,RAND_MAX的范围最少在32767之间(int),即双字节(16位)。
若unsigned int双字节是65535,且0-RAND_MAX每个数字被选中的随机率是相同的。
rand()产⽣的是假随机数,每次执⾏时是相同的,若要不同以不同的值来初始化,初始化的函数就是srand()。
srand函数:头⽂件 <stdlib.h> ,定义函数:void srand(unsigned int seed);函数声明:srand()⽤来设置rand()产⽣随机数时的随机数种⼦,参数seed必须是整数,通常可以⽤time(0)的返回值作为seed.如果每次seed都设置相同的值,rand()产⽣的随机数值每次都⼀样。
srand(unsigned)time(NULL))使⽤系统定时/计数器的值作为随机种⼦每个种⼦对应⼀组根据算法预先⽣成的随机数,所以在相同平台的环境下,不同时间产⽣的随机数是不同的,相应的若将srand(unsigned)tima(NULL)改为任⼀常量,则⽆论何时运⾏,运⾏多少次得到的随机数都是⼀组特定的序列,所以srand⽣成的随机数是伪随机数。
c语言生成随机数在编写程序过程中,我们往往需要计算机替我们生成一系列随机数,特别是使用蒙特卡洛大样本仿真方法时,随机数是否随机往往决定着结果是否精确。
但计算机是通过设置好的一系列程序来运行的,并不能完整模拟随机的概率过程,“随机数”往往稍不注意就变成了“确定数”。
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>int main (void){ int a = rand();printf("%d\n", a);system("pause");return0;}可以看到,无论多少次运行程序,得到的“随机数”永远都是41。
这是因为rand()函数产生的是“伪随机数”,是按照提前设计好的程序以某一个“种子”为起点开始递推产生的一个序列。
默认初始化的种子为“1”int a;srand(1);a = rand();printf("%d\n",a); //41#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>int main (void){ srand(2);int a = rand();printf("%d\n", a);system("pause");return0;}当初始化了“种子”为2后,“随机数”变为了“确定数”45。
一、srand()和rand()函数rand()和srand()要一起使用,其中srand()用来初始化随机数种子,rand()用来产生随机数。
默认情况下随机数种子为1,而相同的随机数种子产生的随机数是一样的,失去了随机性的意义,所以为使每次得到的随机数不一样,用函数srand()初始化随机数种子。
1.rand()与srand()在C语言函数库中包含了一个产生随机数的函数:int rand( );返回的是一个界于0~32767之间的伪随机数,包括0和32767。
注意,这里产生的是伪随机数,不是真正意义上的随机数,看下面的程序:#include "stdlib.h"#include "stdio.h"void main( void ){printf( " %6d\n", rand() );getchar();}程序运行的结果是:346多次运行这个程序,发现每次产生的结果都是346(不同的机器可能产生的结果不一样),这就是所谓的伪随机数。
伪随机数是通过一个公式来运算出来的,所以,每次产生的伪随机数都一样。
那么,如何才能产生真正意义上的随机数呢?这就有一个随机种子的问题。
在C 语言标准函数库中,有另一个配套函数:void srand( unsigned int seed );所以,要产生真正意义上的随机数,那么就要求每次提供的种子不一样,一般情况下,都设置时间为随机函数的种子。
看下面的一段程序:#include "stdlib.h"#include "stdio.h"#include "time.h"void main( void ){int i;srand( (unsigned)time( NULL ) );printf( “ %6d\n”, rand() );}Output6929802621987307342058766992203425051798810104每次运行这个程序,产生的随机数都不一样,这样就达到了随机数的要求了2.random与randomize()打开标准库中的头文件stdlib.h 就会发现有这样的一条语句:#define random(num) (rand() % (num))可见要产生给定范围的随机数,可以使用random()。
C语言中srand(), rand(), time()函数srand函数srand函数是随机数发生器的初始化函数。
原型:void srand(unsigned seed);用法:它需要提供一个种子,这个种子会对应一个随机数,如果使用相同的种子,后面的rand() 函数会出现一样的随机数。
如:srand(1); 直接使用1来初始化种子。
不过为了防止随机数每次重复常常使用系统时间来初始化,即使用time函数来获得系统时间,它的返回值为从00:00:00 GMT, January 1, 1970 到现在所持续的秒数(即从1970年1月1日的00:00:00到当前你所处的时间所经过的秒数),然后将time_t型数据转化为(unsigned)型再传给srand函数,即:srand((unsigned) time(&t));还有一个经常用法,不需要定义time_t型t变量,即:srand((unsigned)time(NULL));直接传入一个空指针,因为你的程序中往往并不需要经过参数获得的t数据。
srand((int)getpid()); 使用程序的ID(getpid())来作为初始化种子,在同一个程序中这个种子是固定的。
例1(C语言)随机输出十个0-100之间的整数程序例1:#include <stdlib.h> /*用到了srand函数,所以要有这个头文件*/#include <stdio.h>#include <time.h> /*用到了time函数,所以要有这个头文件*/#define MAX 10int main( void){int number[MAX] = {0};int i;unsigned int seed;scanf("%d",&seed);/*手动输入种子*/srand(seed);for(i = 0; i < MAX; i++){number[i] = rand() % 100; /*产生100以内的随机整数*/printf("%d ", number[i]);}printf("\n");return 0;}例2(C语言)程序例2:#include <stdlib.h>#include <stdio.h>#include <time.h> /*用到了time函数,所以要有这个头文件*/#define MAX 10int main( void){int number[MAX] = {0};int i;srand((unsigned) time(NULL)); /*播种子*/for(i = 0; i < MAX; i++){number[i] = rand() % 100; /*产生100以内的随机整数*/printf("%d ", number[i]);}printf("\n");return 0;}例3(C++)#include <iostream>#include <ctime>#include <cstdlib>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);}在VC++6.0中输出的结果是:==========================================No.1: 6No.2: 3No.3: 8No.4: 7No.5: 0No.6: 8No.7: 4No.8: 8No.9: 7No.10: 9==========================================rand函数简介功能::伪随机数发生器所属库:stdlib.h用法:需要先调用srand初始化,一般用当前日历时间初始化随机数种子,这样每行代码都可以产生不同的随机数。
用C语言的rand和srand产生伪随机数的方法总结第一篇:用C语言的rand和srand产生伪随机数的方法总结标准库(被包含于中)提供两个帮助生成伪随机数的函数:函数一:int rand(void);从srand(seed)中指定的seed开始,返回一个[seed, RAND_MAX(0x7fff))间的随机整数。
函数二:void srand(unsigned seed);参数seed是rand()的种子,用来初始化rand()的起始值。
可以认为rand()在每次被调用的时候,它会查看:1)如果用户在此之前调用过srand(seed),给seed指定了一个值,那么它会自动调用srand(seed)一次来初始化它的起始值。
2)如果用户在此之前没有调用过srand(seed),它会自动调用srand(1)一次。
根据上面的第一点我们可以得出:1)如果希望rand()在每次程序运行时产生的值都不一样,必须给srand(seed)中的seed一个变值,这个变值必须在每次程序运行时都不一样(比如到目前为止流逝的时间)。
2)否则,如果给seed指定的是一个定值,那么每次程序运行时rand()产生的值都会一样,虽然这个值会是[seed, RAND_MAX (0x7fff))之间的一个随机取得的值。
3)如果在调用rand()之前没有调用过srand(seed),效果将和调用了srand(1)再调用rand()一样(1也是一个定值)。
举几个例子,假设我们要取得0~6之间的随机整数(不含6本身):例一,不指定seed: for(int i=0;i<10;i++){ ran_num=rand()% 6;cout< //…srand((unsigned)time(0));for(inti=0;i<10;i++){ ran_num=rand()% 6;cout<time_t被定义为长整型,它返回从1970年1月1日零时零分零秒到目前为止所经过的时间,单位为秒。
标准库<cstdlib>(被包含于<iostream>中)提供两个帮助生成伪随机数的函数:
函数一:int rand(void);
从srand (seed)中指定的seed开始,返回一个[seed, RAND_MAX(0x7fff))间的随机整数。
函数二:void srand(unsigned seed);
参数seed是rand()的种子,用来初始化rand()的起始值。
可以认为rand()在每次被调用的时候,它会查看:
1)如果用户在此之前调用过srand(seed),给seed指定了一个值,那么它会自动调用srand(seed)一次来初始化它的起始值。
2)如果用户在此之前没有调用过srand(seed),它会自动调用srand(1)一次。
根据上面的第一点我们可以得出:
1)如果希望rand()在每次程序运行时产生的值都不一样,必须给srand(seed)中的seed一个变值,这个变值必须在每次程序运行时都不一样(比如到目前为止流逝的时间)。
2)否则,如果给seed指定的是一个定值,那么每次程序运行时rand()产生的值都会一样,虽然这个值会是[seed, RAND_MAX(0x7fff))之间的一个随机取得的值。
3)如果在调用rand()之前没有调用过srand(seed),效果将和调用了srand(1)再调用rand()一样(1也是一个定值)。
举几个例子,假设我们要取得0~6之间的随机整数(不含6本身):
例一,不指定seed:
for(int i=0;i<10;i++){
ran_num=rand() % 6;
cout<<ran_num<<" ";
}
每次运行都将输出: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<<ran_num<<" ";
}
每次运行都将输出: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<<ran_num<<" ";
}
每次运行都将输出:4 1 5 1 4 3 4 4 2 2
随机值也是在[0,6)之间,随得的值跟srand(1)不同,但是每次运行的结果都相同。
例四,指定seed为当前系统流逝了的时间(单位为秒):time_t time(0):
#include <ctime>
//…
srand((unsigned)time(0));
for(int i=0;i<10;i++){
ran_num=rand() % 6;
cout<<ran_num<<" ";
}
第一次运行时输出: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被定义为长整型,它返回从1970年1月1日零时零分零秒到目前为止所经过的时间,单位为秒。
比如假设输出:
cout<<time(0);
值约为1169174701,约等于37(年)乘365(天)乘24(小时)乘3600(秒)(月日没算)。
另外,关于ran_num = rand() % 6,
将rand()的返回值与6求模是必须的,这样才能确保目的随机数落在[0,6)之间,否则rand()的返回值本身可能是很巨大的。
一个通用的公式是:
要取得[a,b)之间的随机整数,使用(rand() % (b-a))+ a (结果值将含a不含b)。
在a为0的情况下,简写为rand() % b。
最后,关于伪随机浮点数:
用rand() / double(RAND_MAX)可以取得0~1之间的浮点数(注意,不同于整型时候的公式,是除以,不是求模),举例:
double ran_numf=0.0;
srand((unsigned)time(0));
for(int i=0;i<10;i++){
ran_numf = rand() / (double)(RAND_MAX);
cout<<ran_numf<<" ";
}
运行结果为:0.716636,0.457725,…等10个0~1之间的浮点数,每次结果都不同。
如果想取更大范围的随机浮点数,比如1~10,可以将
rand() /(double)(RAND_MAX) 改为 rand() /(double)(RAND_MAX/10)
运行结果为:7.19362,6.45775,…等10个1~10之间的浮点数,每次结果都不同。
至于100,1000的情况,如此类推。