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

news2024/11/22 18:21:32

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.coloradmin.cn/o/828811.html

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

相关文章

1230. K倍区间(超级详细,小白入!!!)

输入样例&#xff1a; 5 2 1 2 3 4 5输出样例&#xff1a; 6 这个题看到区间两个字&#xff0c;两眼一瞪可能就和前缀和差分有关 做题思路&#xff1a; 通过记录每个[1,r]区间值的和,看它前面是否出现过一个[1,l](l<r),使得[l,r]区间的值能除尽k 有同学就好奇&#xff0c;…

re学习(26)攻防世界-re-BABYRE(IDA无法分析出函数-代码混淆)

题目链接&#xff1a;https://adworld.xctf.org.cn/challenges/list elf是一种对可执行文件&#xff0c;目标文件和库使用的文件格式&#xff0c;跟window下的PE文件格式类似。载入IDA后如果需要对此文件进行远程调试&#xff0c;需要用linux系统&#xff0c;比如说Ubuntu&…

卡了大半天的联调问题

卡了大半天的联调问题 问题&#xff1a;别人dubbo总是调不通我的服务 问题&#xff1a;别人dubbo总是调不通我的服务 org.apache.dubbo.remoting.RemotingException: client(url: dubbo://192.168.56.1:28085/com.alibaba.cloud.dubbo.service.DubboMetadataService?actives1…

8.2day03 Redis入门+解决员工模块

概述 在我们日常的Java Web开发中&#xff0c;无不都是使用数据库来进行数据的存储&#xff0c;由于一般的系统任务中通常不会存在高并发的情况&#xff0c;所以这样看起来并没有什么问题&#xff0c;可是一旦涉及大数据量的需求&#xff0c;比如一些商品抢购的情景&#xff0…

Jest和Mocha对比:两者之间有哪些区别?

目录 什么是单元测试&#xff1f; Jest和Mocha介绍 Jest Jest的特点&#xff1a; Jest的使用限制 Mocha Mocha的特点 使用Mocha的限制 Jest和Mocha的全面比较 我们应该使用哪个测试框架&#xff1f; 结论 什么是单元测试&#xff1f; 所谓单元测试&#xff0c;是对软…

LabVIEW开发多材料摩擦电测量控制系统

LabVIEW开发多材料摩擦电测量控制系统 摩擦电效应是两个物体摩擦在一起&#xff0c;电荷从一个物体转移到另一个物体的现象&#xff0c;从而导致两个物体携带相等和相反的电荷。接触和充电是主导该过程的两个关键因素。当静电荷累积到一定水平时&#xff0c;可能会出现放电现象…

Profile多环境配置以及结合Maven如何使用

文章目录 一、前言二、如何使用profile多环境配置2.1、编写各环境的配置文件2.2、如何让配置文件生效 三、结合Maven使用 一、前言 我们在开发项目的过程中&#xff0c;会遇到需要使用多套环境配置的情况&#xff0c;因为不同环境可能存在不同的配置&#xff0c;比如数据库连接…

eNSP 路由器启动时一直显示 # 号的解决办法

文章目录 1 问题截图2 解决办法2.1 办法一&#xff1a;排除防火墙原因导致 3 验证是否成功 1 问题截图 路由器命令行一直显示 # 号&#xff0c;如下图 2 解决办法 2.1 办法一&#xff1a;排除防火墙原因导致 排查是否因为系统防火墙原因导致。放行与 eNSP 和 virtualbox 相…

Shiro框架基本使用

一、创建maven项目&#xff0c;引入依赖 <dependencies><dependency><groupId>org.apache.directory.studio</groupId><artifactId>org.apache.commons.codec</artifactId><version>1.8</version></dependency><!-- …

A-LOAM安装与配置

GitHub https://github.com/HKUST-Aerial-Robotics/A-LOAM 依赖项 需要安装Ceres Slover和PCL PLC之前已经安装过&#xff0c;因此只需要安装Ceres Solver 编译安装Ceres Slover报错 官方的安装指南 http://ceres-solver.org/installation.html 一开始是git下来的最新版本的…

r一个高性能、无侵入的 Java 性能监控和统计工具

背景 随着所在公司的发展&#xff0c;应用服务的规模不断扩大&#xff0c;原有的垂直应用架构已无法满足产品的发展&#xff0c;几十个工程师在一个项目里并行开发不同的功能&#xff0c;开发效率不断降低。 于是公司开始全面推进服务化进程&#xff0c;把团队内的大部分工程…

官网下载历史版本Android studio

有时我们个更新到了最新版本的AndroidStudio&#xff0c;但发现最新版的有一些bug影响使用&#xff0c;这时我们需要将新版卸载安装到旧版本&#xff0c;本文便是记录如何在官网下载旧版本的android studio。 下载地址 1、查看Release notes 2、查看过往版本 3、点击下载旧版…

Jenkins持续集成实现过程(简易版)

我就用一台服务器模拟&#xff0c;gitlab用公司现成的&#xff0c;jenkins安装发版都是在同一台服务器上 安装Jenkins&#xff08;Docker&#xff09; 宿主机上创建数据映射目录 mkdir /data/jenkins给映射目录权限&#xff0c;不然jenkins用不了 chmod -R 777 /data/jenkin…

【es6】Promise实现

友情链接 关于promise的介绍&#xff0c;请看此篇水文 本篇文章只是介绍实现promise以及promise常用方法。 正文 Promise使用 let promise new Promise((resolve,reject)>{resolve(success); //这里如果是reject(fail) }); promise.then((res)>{console.log(res); …

企业AD域管理:ADManager Plus助您轻松掌控全局

在现代企业中&#xff0c;Active Directory&#xff08;AD&#xff09;域是一个至关重要的组成部分。它作为一种身份验证和授权机制&#xff0c;管理着企业网络中的用户、计算机、组和其他资源。然而&#xff0c;随着企业规模和复杂性的不断增长&#xff0c;AD域的管理变得越来…

深入挖掘地核和地幔之间的相互作用

一本新书介绍了我们在理解地核-地幔相互作用和共同进化方面的重大进展&#xff0c;并展示了提高我们对地球深层过程的洞察力的技术发展。 与地核-地幔共同演化相关的地球深层结构和动力学的图示。图片来源&#xff1a;白石千寻 Editors Vox是 AGU 出版部的博客。 地球深层内部很…

螺杆支撑座使用深沟球轴承和角接触球轴承的区别?

螺杆支撑座是连接丝杆和电机的轴承固定座&#xff0c;与滚珠螺杆搭配使用&#xff0c;能够获得高刚性、高精度的稳定的回转性能&#xff0c;因此被广泛应用在各行各业中。 使用螺杆支撑座之所以能够获得稳定的回转性能&#xff0c;主要是因为最佳轴承的使用&#xff0c;通俗点说…

IDEA中怎么将代码提交代码到远程仓库

假设代码已经写好,现在准备提交到远程仓库 git会自动帮我们在远程托管平台中创建一个仓库这里我选用的是gitee 如果还没有注册gitee 请先去注册,第一次使用需要登录gitee账号 登录我们自己的gitee账号,会发现git自动创建了一个仓库 如果我们又修改了 代码,想重新提交到远程仓库…

DreamBooth为何有能力让第一个应用创建者年赚2500万美金?

DreamBooth 是一种个性化的文本到图像生成模型&#xff0c;它可以通过向扩散模型&#xff08;比如Stable Diffusion&#xff09;中注入少量主体对象&#xff0c;从而达到对基础模型的微调。使用微调后的模型可以生成在不同的场景、姿势和视角中的该主体上下文图像。 Dreamboot…

单通道 6GSPS 16位采样DAC子卡模块--【资料下载】

FMC147是一款单通道6.4GSPS&#xff08;或者配置成2通道3.2GSPS&#xff09;采样率的12位AD采集、单通道6GSPS&#xff08;或配置成2通道3GSPS&#xff09;采样率16位DA输出子卡模块&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.4规范&#xff0c;该模块可以作为一个理想…