【c++】rand()随机函数的应用(一)——rand()函数详解和实例

c++语言中可以用rand()函数生成随机数,今天来探讨一下rand()函数的基本用法和实际应用。

本系列文章共分两讲,今天主要介绍一下伪随机数生成的原理,以及在伪随机数生成的基础上,生成随机数的技巧,下一讲主要介绍无重复随机数生成的方法和舒尔特方格数字生成的实例。本文采用循序渐进的方式逐步介绍,并且贴上了实际测试的代码和结果。有不详和不实之处,请各位大神批评指正。

 

目录

一、rand()函数的几个要点

1、rand()函数所在库

2、rand()函数的范围

3、rand()函数为伪随机数

4、线性同余算法简介

二、rand()函数的基本使用技巧

1、单独使用

2、配合srand()函数使用

(1)srand()函数原型

(2)所在库也是cstdlib

(3)srand()的作用

3、配合time()或getpid()使用

(1)time(NULL)函数

(2)getpid()函数

三、rand()函数的扩展功能

1、生成0~n(n>1)随机整数

2、生成n~m(n1)范围内的随机整数,m-n>


一、rand()函数的几个要点

1、rand()函数所在库

rand()函数原型:int rand(void); 

所在的库为cstdlib,所以使用时需要引入cstdlib头文件。

2、rand()函数的范围

当为int型时,随机数的范围为0~32767。

3、rand()函数为伪随机数

rand()的内部实现是用线性同余法做的,它不是真的随机数,因其周期特别长,故在一定的范围里可看成是随机的。

4、线性同余算法简介

线性同余算法是一种迭代算法,每次迭代计算出的结果就是伪随机数,其迭代公式为:

x_{n+1}=(a*x_{n}+c) mod(m)                                                                    (1)                      

式中:

x_{n+1}为第n+1次迭代值;

x_{n}为第n次迭代值;

ac为常数;

m为随机数范围(由rand()数据类型确定,如果为int,则为32768);

公式第一次迭代

x_{1}=(a*x_{0}+c) mod(m)

所用的x_{0}为初始值,也称为种子(seed),也就是acm都确定后,随机数的序列是由x_{0}值决定的,而系统默认其值为1

二、rand()函数的基本使用技巧

1、单独使用

单独使用rand()函数示例代码如下:

#include <iostream>
#include <cstdlib>
#include <windows.h>
using namespace std;int main()
{while(1){cout<<rand()<<endl;Sleep(1000);	}	
}

经过多次测试,发现这样一个规律,每次运行程序时,产生的随机数序列都是一样的,都固定不变为[41,18467,6334,26500,...],如下图所示。因为我们在程序中没有设定x_{0},而系统默认值为1,所以根据(1)式算出来的为随机数序列值都是一样的。

41
18467
6334
26500
19169
15724
11478
29358
26962
24464
5705
28145
23281
16827
9961
491

2、配合srand()函数使用

(1)srand()函数原型

void srand (usigned int seed)

(2)所在库也是cstdlib

(3)srand()的作用

用来设置rand()产生随机数时的随机数种子。参数seed是整数,当改变seed值时,产生的伪随机数序列就会发生改变。在程序中设定seed=0,如下所示。

#include <iostream>
#include <cstdlib>
#include <windows.h>
using namespace std;int main()
{while(1){srand(0);cout<<rand()<<endl;Sleep(1000);	}	
}

运行程序后,发现伪随机数序列发生变化了,如下图所示。

38
7719
21238
2437
8855
11797
8365
32285
10450
30612

3、配合time()或getpid()使用

使用srand()函数,改变seed数值,可以改变伪随机数的序列。每次要想生成不同的伪随机数序列,就要手动改变seed值,也不是很方便。所以,最好的办法是每次运行程序,seed值都可以自动改变。通常可以利用time(NULL)或getpid()的返回值作为seed。

(1)time(NULL)函数

time(NULL)的返回值为当前时间的时间戳(以秒为单位),比如2023-8-2 17:19:04对应的时间戳数值为1690967944。所以每次运行时间不一样,通过srand()函数给rand()函数设定的seed的值x_{0}也不一样,因此产生的随机数序列也就不一样了。

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <windows.h>using namespace std;int main()
{srand(time(NULL));while(1){cout<<rand()<<endl;Sleep(1000);}}

下边是两次运行的结果,可见产生的随机序列不一样了。

28572
10647
18752
10924
2469
21939
7821
17697
30059
16936
9742
13113
23443
17313
28729
2282
24264
19083
6048
13814
26147
8260
3416
16741
2642
15228
4765
25104
30495
26600

(2)getpid()函数

getpid是一种函数,功能是取得进程识别码,许多程序利用取到的此值来建立临时文件,以避免临时文件相同带来的问题。

getpid()函数需要引入的头文件有stdio.h、unistd.h和sys/types.h。

调试程序代码如下:

#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
using namespace std;int main()
{srand(getpid());while(1){cout<<rand()<<endl;Sleep(1000);	}	
}

分别执行两次程序生成的伪代码随机数序列也不相同,结果如下:

5721
5487
18939
28251
29922
6470
2914
16807
14781
32440
28228

15685
28899
30711
4193
17378
25105
4253
4132
15548
3930
16509
23440
17039

getpid函数与time(NULL)函数不同之处是:

第一、time(NULL)获取的是时间戳值,所以与程序的进程无关,无论进程相同还是不同,只要调取函数的时间不一样,那么生成的seed值就不一样。

第二、getpid函数是程序的进程识别码,所以在同一个程序的进程内多次调用函数,生成的seed值是一样的。只有在不同的进程内调用,seed值才会改变。

三、rand()函数的扩展功能

1、生成0~n(n>1)随机整数

rand()函数生成的随机数范围为0~32767,那么要想让范围变为0~m(m<32767),只需要用rand()对m+1求余即可。

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <windows.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
using namespace std;int main()
{int m;cin>>m; 
//	srand(getpid());srand(time(NULL));while(1){cout<<rand()%(m+1)<<endl;Sleep(1000);}}

2、生成n~m(n<m,m-n>1)范围内的随机整数

要想让rand()函数生成的随机数范围为n~m(n<m,m-n>1),只需要用rand()对(m-n+1)求余,再加n即可。

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <windows.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
using namespace std;int main()
{int m,n;cin>>n>>m; 
//	srand(getpid());srand(time(NULL));while(1){cout<<rand()%(m-n+1)+n<<endl;Sleep(1000);}}

(未完待续)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/26228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

glb/gltf文件打包的几种方法

glb/gltf文件打包的几种方法 在3d开发过程中,发现建模师给的文件越来越多,越来越大,下载的越来越慢,场景加载的时间越来越长,就想着要解决这个问题。 在偶然中发现glb/gltf文件也是可以压缩的,今天咱们就来看看压缩的两种方法。 一、gltfpack 首先要说明的是我不推荐使…

从零开始打造你的书店小程序商城

随着互联网的发展&#xff0c;线上商城成为了书店经营的重要方式之一。如何快速搭建一个符合书店特点的小程序商城呢&#xff1f;下面将为您详细介绍利用乔拓云平台搭建一个符合书店特点的小程序商城的步骤。 首先&#xff0c;登录乔拓云平台&#xff0c;进入商城后台管理页面。…

rust-异步学习

rust获取future中的结果 两种主要的方法使用 async: async fn 和 async 块 async 体以及其他 future 类型是惰性的&#xff1a;除非它们运行起来&#xff0c;否则它们什么都不做。 运行 Future 最常见的方法是 .await 它。 当 .await 在 Future 上调用时&#xff0c;它会尝试把…

SpringMVC概述、SpringMVC的工作流程、创建SpringMVC的项目

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaweb 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 Spring MVC入门 一、Spring MVC概述二、入门案例2.1导入Sp…

微信现在怎么加好友最有效?

微信作为如今当之无愧的国民 App&#xff0c;基本已经成为了国内用户的首选社交软件。 无论是日常交友&#xff0c;还是商务交流&#xff0c;基本都能在微信上完成。 主动加人最好的办法就是做矩阵&#xff0c;如果是被动加人的话方式就很多。 说说主动加人做矩阵吧。 微信目前…

虚拟化总结

写文章 点击打开Jack Yuan的主页 看这篇就够了,最全最干的Linux系统安装教程 老羊皮 老羊皮 央企在岗,数据控,资源控,圆子控。 ​关注他 1 人赞同了该文章 写在前面: (1)本次选用以 DELL 全新服务器为例,来安装 RedHat 操作系统; (2)教程共包含以下 4 部分,请一定…

小白到运维工程师自学之路 第六十五集 (docker-compose)

一、概述 Docker Compose 的前身是 Fig&#xff0c;它是一个定义及运行多个 Docker 容器的工具。可以使用YAML文件来配置应用程序的服务。然后&#xff0c;使用单个命令&#xff0c;您可以创建并启动配置中的所有服务。Docker Compose 会通过解析容器间的依赖关系&#xff08;…

AOF日志:宕机了,Redis如何避免数据丢失

当服务器宕机后&#xff0c;数据全部丢失&#xff1a;我们很容易想到的一个解决方案是从后端数据库恢复这些数据&#xff0c;但这种方式存在两个问题&#xff1a;一是&#xff0c;需要频繁访问数据库&#xff0c;会给数据库带来巨大的压力&#xff1b;二是&#xff0c;这些数据…

Ubuntu 22.04安装和使用ROS1可行吗

可行。 测试结果 ROS1可以一直使用下去的&#xff0c;这一点不用担心。Ubuntu会一直维护的。 简要介绍 Debian发行版^_^ AI&#xff1a;在Ubuntu 22.04上安装ROS1是可行的&#xff0c;但需要注意ROS1对Ubuntu的支持只到20.04。因此&#xff0c;如果要在22.04上安装ROS1&am…

前端笔试---acm模式

前言 之前一直刷力扣&#xff0c;昨天做了小红书笔试&#xff0c;发现是acm模式&#xff0c;不太熟悉&#xff0c;特此总结。其实如果是acm模式就需要自己写一下输入输出。前端一般有两个选择&#xff0c;一个是基于 V8 环境&#xff0c;另一个是基于 node。 V8 // 对于有多…

Qt编写自定义控件:自定义表头实现左右两端上部分圆角

如上图&#xff0c;左上角和右上角凸出来了。设置表格圆角和表头圆角和QHeaderView::section圆角都不管用。解决此问题需要重写QHeaderView的paintSection()函数&#xff1a; class CustomHeaderView : public QHeaderView { public:explicit CustomHeaderView(Qt::Orientati…

补充JDK源码-IDEA集成工具

在阅读JDK8源码的时候发现&#xff0c;只有一小部分常用包是存在源码及其注释的&#xff0c;而很多内部包是没有源码&#xff0c;class文件在阅读的时候对阅读者十分不友好。在网上搜集了很多资料都没有解决问题。 解决问题办法&#xff1a;参考文档。本文主要是根据这篇文章记…

C# MVC controller 上传附件及下载附件(笔记)

描述:Microsoft.AspNetCore.Http.IFormFileCollection 实现附件快速上传功能代码。 上传附件代码 [Route("myUploadFile")][HttpPost]public ActionResult MyUploadFile([FromForm] upLoadFile rfile){string newFileName = Guid.NewGuid().ToString("N"…

服务器带宽独享跟共享有什么区别103.36.166.x

独享带宽 独享带宽针对对带宽有较高的要求&#xff0c;其业务的内容和性质决定只有使用独立的带宽资源才能满足品质的需求&#xff0c;而这种只给单独客户使用的带宽资源称为独享带宽. 使用独享带宽&#xff0c;整个带宽资源归属于一个客户 独享带宽的优点是可自由使用带宽量…

西电-印刷电路板(PCB)设计指南0903完整版

PCB设计是以电路原理图为根据,实现电路设计者所需要的功能。 最近我找到一份西安电子科技大学的PCB设计指南的课件,课件内容非常夯实详尽: 分为通用电路篇和高速电路篇,包含了: PCB基础知识 PCB设计步骤和规范 电流路径分析、常见类型PCB设计 传输线与阻抗匹配、信号…

react icon ant简单使用

refer&#xff1a; 文字提示 Tooltip - Ant Design 1.首先保证已经引入了Ant 2.在组件&#xff08;页面&#xff09;引入tooltip import { Form, Tooltip } from antd; 3.在合适的位置使用tooltip&#xff1a; <span>寿命 <Tooltip title"这是寿命的说明&quo…

知识分享和Tomcat简单部署press应用

一、简述静态网页和动态网页的区别。 静态网页: 静态网页是指运行于客户端的程序、网页、组件、纯粹HTML格式的网页; 如果有涉及网页内容的修改&#xff0c;就要修改源文件&#xff0c;重新上传到服务器。而且当网站信息量很大的时候&#xff0c;网页制作和维护都非常困…

实力认证 | 百分点科技蝉联中国大数据企业50强

近日&#xff0c;第八届中国大数据产业生态大会在京召开 &#xff0c;本届大会以“数实共融 生态共建”为主题&#xff0c;由赛迪传媒、大数据产业生态联盟、《软件和集成电路 》杂志社联合主办。会上颁布多个奖项&#xff0c;百分点科技斩获2023中国大数据企业50强、金沙奖“…

为Git仓库设置签名信息

前言 在首次使用git版本库或创建新的仓库时&#xff0c;需要为其仓库设定管理员和管理员邮箱。 在为仓库添加管理员和邮箱地址时&#xff0c;有以下两种情况&#xff1a; &#xff08;1&#xff09;全局模式&#xff1a;首次创建&#xff0c;后面做为默认使用&#xff0c;对当…

springboot中排除数据源的自动配置方式循环依赖是什么意思?

在Spring Boot中&#xff0c;有时候我们希望排除自动配置的数据源&#xff0c;而使用自定义的数据源。为了达到这个目的&#xff0c;可以使用EnableAutoConfiguration注解的exclude属性来排除某些自动配置类。 关于循环依赖的问题&#xff0c;它发生在一个或多个对象之间出现了…