伪随机数C语言编程
在程序设计中,有时会用到随机数。本文介绍在 Linux 编程环境下,如何生成伪随机数。
什么是伪随机数
伪随机数是通过一个确定性的算法计算出来的“似乎”是随机的数序,因此伪随机数实际上并不随机。在计算伪随机数时,假如初始值不变的话,那么伪随机数的数序也不变。
伪随机数的优点
要产生真正的随机数,必须使用专门的设备,比如热噪信号、量子力学效应、放射性元素的衰退辐射,或使用无法预测的现象等。而伪随机数计算比较简单,不需要外部特殊硬件的支持,因此在计算机科学中伪随机数依然被使用。
伪随机数的缺点
由于伪随机数不是真的随机数,在有些方面它们不能被使用。例如在密码学中使用伪随机数要小心,因为其可计算性是一个可以攻击的地方。统计学、蒙特·卡罗方法上使用的伪随机数也必须挑选周期极长、随机性够高的随机函数,以确保计算结果有足够的随机性。
利用 rand()
函数生成伪随机数
函数原型:
//需要包含头文件 <stdlib.h>
int rand(void);
Linux 中的rand()
函数会返回一随机数值,其范围在0
至RAND_MAX
间。这里的RAND_MAX
定义在stdlib.h
中(如下图的128行所示),值为 2147483647(=2^31-1)。
以下例子利用 rand()
函数生成伪随机数。
#include <stdlib.h>
#include <stdio.h>
#define RAND_NUM 5
int main(int argc, char *argv[])
{
for(int i=0; i< RAND_NUM; ++i)
printf( "%d ", rand() );
printf("\n");
return 0;
}
编译后连续运行两次,结果是:
$ ./rand
1804289383 846930886 1681692777 1714636915 1957747793
$ ./rand
1804289383 846930886 1681692777 1714636915 1957747793
为什么会这样呢?
计算机产生的伪随机数是通过递推的方法得来的,必须要有一个初始值,也就是通常所说的种子。如果不对种子进行初始化,那么计算机会使用一个默认值。由于两次运行中初始值一样(都是默认值),递推公式也一样,所以才有完全一样的伪随机序列。
对于rand()
函数,如果未设随机数种子,rand()
在被调用时会自动设随机数种子为1
。
要想避免这种结果,就需要在每次程序运行时对种子进行初始化 ,且初始值不一样(比如到目前为止经过的时间 )。
获取当前时间(以秒计算)
函数原型:
// 需要包含头文件 <time.h>
time_t time (time_t* timer);
time_t
其实是一个长整形。
time_t time (time_t* timer)
函数的用法是:
当参数为NULL的时候,返回从1970年1月1日0时0分0秒到此时的秒数;当参数不为NULL的时候,不仅返回从1970年1月1日0时0分0秒到此时的秒数,还把返回值存储到参数指向的time_t
类型的变量里。
设置种子
函数原型:
// 需要包含头文件 <stdlib.h>
void srand (unsigned int seed);
srand
函数把种子值作为参数。结合函数time_t time (time_t* timer)
,我们可以这样设置种子:
srand( (unsigned int)time(NULL) );
参考代码
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define RAND_NUM 5
int main(int argc, char *argv[])
{
srand( (unsigned int)time(NULL) );
for(int i=0; i< RAND_NUM; ++i)
printf( "%d ", rand()%100 );
printf("\n");
return 0;
}
实验结果如下:
$ ./rand
61 71 64 35 13
$ ./rand
50 11 83 43 69
$ ./rand
68 32 35 94 83
【完】
参考资料
http://txgcwm.github.io/blog/2013/07/07/linuxxia-cyu-yan-wei-sui-ji-shu-bian-cheng/
https://zh.wikipedia.org/wiki/%E4%BC%AA%E9%9A%8F%E6%9C%BA%E6%80%A7
https://blog.csdn.net/duyiwuer2009/article/details/49497199