目录

  • 前言
  • 一、rand函数
    • 代码1:
    • rand函数实现:
  • 二、srand函数
    • srand函数实现
    • 代码2:
  • 三、time函数
      • 代码3:
    • rand和srand用法注意点
  • 四、产生特定范围内的随机数
    • 代码5:
  • 五、疑问
  • 后记

前言

之前在敲代码的时候用过rand函数,当时只是知道了rand函数要配合srand函数一起使用,才能达到产生一个随机数的目的,具体原因是什么则一知半解,后来闲着无事,查找了一下资料,差不多弄懂了。不过碍于本人水平有限,可能会有些地方理解有误,敬请给读者批评指正,并提出宝贵意见。


一、rand函数

rand函数是用来产生一个随机数,返回值为0~RAND_MAX,RAND_MAX不得小于32767,在编译器中可以通过查看定义来查看这个数具体是多少。不过这数字并不是真正的随机,而是一种伪随机数。


在cplusplus网站上关于rand函数给出的解释如下:
rand函数解释

大致意思就是rand函数每次通过一个算法产生一个随机的数字,而这个算法又使用种子来产生随机数。

至于为什么说rand函数产生的数字是伪随机数,我们用一串代码来解释

代码1:

#include<stdio.h>
#include<stdlib.h>
int main()
{int random = 0;for (int i = 0; i < 10; i++){random = rand();           //用rand产生一个随机数printf("%d\n", random);}return 0;
}

程序运行结果:

似乎的确是产生了10个随机的数字,但是当我们再一次运行程序,甚至我们把程序关闭再次执行相同的程序时,产生的还是这10个数字。很明显这就不是我们想要的随机数了。

产生这样结果的原因是什么呢?正如前面我们所说,rand函数所产生的数是基于一个依赖于种子的算法来实现的,而这个种子在你每次启动电脑时就确定了。因此每次rand产生的数字也当然是一样的。

至于rand函数所使用的算法是什么,在Dennis M.Ritchie(C语言之父)所著的《C程序设计语言》一书中给出了一种算法:

rand函数实现:

unsigned long int next = 1;
int rand(void)
{next = next * 1103515245 + 12345;return (unsigned int)(next / 65536) % 32768;
}

next 就是我们前面所说的种子,由此大家应该知道为什么我们运行上面的代码时,产生的10个数字每次都是一样的。

二、srand函数

在前言中我们提到,rand要配合srand来使用,那么srand又是什么呢?
同样的在cplusplus中我们可以查到srand函数的解释:srand就是用来初始化我们前面所说的种子,这样程序在每次运行时都会有不同的种子值,从而rand函数就会生成一个真正的随机数。
在Dennis M.Ritchie的《C程序设计语言》中给出了srand函数的一种算法:

srand函数实现

unsigned long int next = 1;void srand(unsigned int seed)
{next = seed;
}

很明显,srand可以初始化我们的种子,但是要怎么进行初始化呢,我们先自己输入一个参数,手动对srand进行初始化。

代码2:

#include<stdio.h>
#include<stdlib.h>
int main()
{int random = 0;int n = 0;scanf("%d", &n);srand(n);     //用srand初始化种子for (int i = 0; i < 10; i++){random = rand();           //用rand产生一个随机数printf("%d\n", random);}return 0;
}

当我们输入 2,3,4…时结果如下:

当我们输入不同的n时,rand函数都给出了不同的值,但是当我们输入两组相同的n时,rand的结果都是一样的。也就是说,我们手动地让srand初始化种子,所以此时的随机数可以说成是在认为控制下的随机数,因此它也不是真正意义上的随机数。为了解决这一问题,我们引入time()函数。

三、time函数

同样的,我们先看cplusplus中给出的解释:

time函数会获取电脑的当前日历时间,并返回从这一时间到1970年1月1日00:00的秒数。


我大概地算了一下,从1970年1月1日00:00到运行程序时的时间,就是程序所运行的结果。

因此我们可以将time函数的返回值作为srand的参数来初始化种子。
代码如下:

代码3:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{int random = 0;srand((unsigned int )time(NULL));     //用srand初始化种子for (int i = 0; i < 10; i++){random = rand();        //用rand产生一个随机数printf("%d\n", random);}return 0;
}

运行结果:

再次运行程序的话,产生的两组数字基本上不会一样。

rand和srand用法注意点

在代码3中,如果我们将srand()放入 for循环中,运行的结果会是什么呢?

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{int random = 0;//srand((unsigned int )time(NULL));     //用srand初始化种子for (int i = 0; i < 10; i++){srand((unsigned int )time(NULL));     //用srand初始化种子random = rand();       //用rand产生一个随机数printf("%d\n", random);}return 0;
}


产生了10个一样的数字,如果再次运行一下程序就会生成另一组10个完全相同的数字

这是因为每次循环中,虽然我们都会重置种子,但不要忘了,种子是由srand函数调用time函数生成,而time函数生成的数是当前时间距离1970年1月1日凌晨的秒数,单位是秒,而对于我们这样一个小的程序来说,电脑根本用不了1秒的时间,因此每次设置的种子其实都是一样的。而当我们再次运行程序时(我相信你的手速肯定达不到1秒之内完成这一系列操作)已经间隔了几秒钟的时间,种子已经不一样了,所以两次运行之间产生了不同的数字。

因此当我们想要随机产生一组数字时,要将srand放在循环体外,每次运行程序时,只重置一次种子。

四、产生特定范围内的随机数

当我们使用了time函数后,rand函数便会随机产生一个0~RAND_MAX之间的数,但是在大多数情况下,我们只需要某一个区间内的随机数就可以了,那么如何做到呢?
例如我们想要得到[a,b]区间内的随机数,我们只需要将rand生成的数模上(b-a+1)再加上a即可,即:
random = rand()%(b-a+1)+a。
因为对于任意两个正整数x,n,x%n所得到的结果一定位于区间[0,n-1],
因此random%(b - a+1)∈[0,b-a],random%(b - a+1)+ a∈[a,b]

代码5:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{int random = 0;srand((unsigned int )time(NULL));     //用srand初始化种子for (int i = 0; i < 10; i++){a = rand()%51+50;      //用rand产生一个[50,100]的数字 rand()%(100-50+1)+50∈[50,100]printf("%d\n", a);}return 0;
}

五、疑问

对于代码3,当我们多次运行后,可以发现,产生的第一个数字总是在慢慢的增加,并且每两次运行之间的差值都很小


其他的数字之间也有一种变化规律,这似乎又不满足我们想要的结果。我的理解是,我们每两次执行程序之间,间隔的时间只有几秒钟的时间,因此time函数的返回值很接近,即种子的值其实也很接近,所以最后得到的随机数也很接近。

unsigned long int next = 1;
int rand(void)
{next = next * 1103515245 + 12345;return (unsigned int)(next / 65536) % 32768;
}

以Dennis M.Ritchie所给的代码为例,逐渐增加则是因为,第二次运行时,种子的值肯定比第一次运行的值大,因此(next / 65536) % 32768的值,第二次通常会比第一次大(当然这也不是绝对的),当结果逐渐增大到超过32768后,又会变成一个接近0的正整数,然后再次逐渐增大。

猜想:在同一台电脑上,同一款IDE的不同版本(例如VS2019和VS2010)下同时运行代码3,最后产生的随机数是一样的。

后记

碍于本人水平有限,最后的疑问,也是我不太明白的地方。如果有读者能够理解的,也希望能帮忙解释一下。如果文中有错误和不妥之处,还请各位读者批评指正,谢谢。

rand和srand函数的用法相关推荐

  1. rand()和srand()函数的用法

    一.rand() rand()函数用来产生随机数,但是,rand()的内部实现是用线性同余法实现的,是伪随机数,由于周期较长,因此在一定范围内可以看成是随机的. rand()会返回一个范围在0到RAN ...

  2. C语言之rand()和srand()函数

    1.rand().srand()函数介绍 srand 初始化随机种子,rand 产生随机数 定义函数:int rand(void) 函数功能:产生随机数 函数说明:rand的内部实现是用线性同余法做的 ...

  3. C语言rand和srand函数的简单介绍和用法

    目录 介绍: 用法: 介绍: 在c语言中,我们想要在一个范围内随机生成一个数字,我们就需要用到rand函数,生成大小为0到32767的整数,但仅靠rand生成的数是伪随机的数,如下: 第一次运行n次: ...

  4. 随机生成函数rand与srand函数

    一.rand函数 在需要用到随机生成函数时,我们第一想到的也是rand函数 那么这个函数的基本用法是什么呢? 首先,使用rand函数需要用到头文件#include<stdlib.h> 接下 ...

  5. rand()和srand()函数

    srand 初始化随机种子,rand 产生随机数. rand函数 头文件: <stdlib.h> 定义函数:int rand(void) 函数功能:产生随机数 函数说明:因为rand的内部 ...

  6. C语言学习笔记07-2-循环的游戏实验:猜数字(附rand、srand函数说明)

    C语言猜数字游戏实验(07-1笔记的补充) 在C/C++编程练习中代码太多,不能明显体现有关分支.循环语句结构的实验变化,在此处单独归纳汇总一份我尝试过的三次猜数字游戏设计. 猜数字初版 #inclu ...

  7. 随机种子关于rand和srand函数使用的一点心得

    每日一贴,今天的内容关键字为随机种子 在c语言里面,两个函数包括在<stdlib.h>头文件里面,c++里面,标准库<cstdlib>(被包括于<iostream> ...

  8. 随机数rand和srand的用法

    有关于rand函数跟srand函数的用法 #include <stdio.h> #include <math.h> int main(){printf("%d\n&q ...

  9. srand、rand、time函数的正确使用(猜数字游戏)

    这篇文章我简要介绍srand.rand.time函数的使用,并用他们一起来完成一个猜数字游戏 目录 一.随机数产生函数 1.rand函数, 2.srand函数, 3.time函数, 二.猜数字游戏 1 ...

  10. rand和srand

    rand()和srand()函数我们应该接触的比较多了,之前就遇到过,弄懂了,但是现在又忘了.再次遇见写篇文章记录一下. srand()用来设定一个随机数种子,其参数必须是整数,不同的随机数种子使ra ...

最新文章

  1. Eigen 学习笔记
  2. Tidb集群加mysql_TiDB - 快速入门,集群搭建
  3. mysql 5.7 super_MySQL 5.7 下的对super用户只读
  4. Go语言(golang)开源项目大全
  5. 和我一起打造个简单搜索之ElasticSearch入门
  6. linux下完全删除mysql
  7. 服务器清理虚拟内存工具,win2008内存释放工具
  8. 实对称矩阵可对角化证明
  9. 怎样在视频上加字幕,分享视频添加字幕的小技巧
  10. c语言pow的作用,c语言中pow函数的用法是什么?
  11. WEB自动化测试学习进度
  12. 股票涨跌和买卖预测计算公式
  13. ES分片UNASSIGNED解决方案(ALLOCATION_FAILED,REPLICA_ADDED,NODE_LEFT,REINITIALIZED,CLUSTER_RECOVERED等等)
  14. 线程池及其原理和使用
  15. 内网环境部署zabbix5.0版本监控(一)
  16. 信息安全第五章 操作系统安全
  17. 深入理解Camera 基础知识点
  18. 牛客网视频总结5(二叉树)
  19. 使用Python爬取豆瓣电影 Top 250
  20. 华为计算机黑屏怎么办,华为电脑开机屏幕没反应(开机黑屏的3个原因及解决法)...

热门文章

  1. springboot+vue医院预约挂号系统java
  2. 魅族16 USB连接计算机,在魅族16x中连接电脑的方法分享
  3. Microsoft Office 2013 word MathType 报错 (MathPage.wll)
  4. strpos使用不当引发漏洞
  5. 教你 用c语言输出乘法口诀表 一giao我嘞gaiogiao
  6. 3.注册后台处理逻辑编写
  7. list to torch
  8. Python-----从所示的三门成绩中,生成个人成绩单,并显示每个人选修了几门课程。
  9. 如何设置计算机桌面待办事项,电脑上怎么设置重要事情提醒?怎么在电脑桌面便签上设置重要事项提醒...
  10. 世界互联网大会上有哪些黑客科技值得关注?