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

2023-11-18

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);
	}
	
}

(未完待续)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • 无限循环与无限递归。两者都是未定义的吗?

    无副作用的无限循环是未定义的行为 看here https coliru stacked crooked com view id 24e0a58778f67cd4举个例子参考参数 https en cppreference com w cpp
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template

随机推荐

  • [编写高质量代码:改善java程序的151个建议]建议103 反射访问属性或方法时将Accessible设置为true...

    转载于 https www cnblogs com akingseu p 3506576 html
  • canvas小练习之鼠标粒子特效

  • Qt 笔记5--Qt 拉伸窗体

    Qt 笔记5 Qt 拉伸窗体 正常情况下 Qt主窗体拉伸 但内部子窗体大小及位置并未发生该表 导致出现一部分空白区域 因此实际中为了美观需要实现其动态拉伸和调整效果 以下为笔者通过重新resizeEvent方法实现的一个简单拉伸案例 相应学
  • 小程序如何进行分包详细介绍

    微信小程序开发过程中 随着业务不断迭代 程序包的体积越来越大 使用分包加载是开发者必须面对的问题 正常情况下 小程序首次启动时 会将整个代码包下载下来 所以如果代码包过大 会影响小程序首次启动时间 因此微信官方对小程序代码包做了大小限制 官
  • JetBrains Resharper 2019.1.3的安装、破解、使用

    最近在浏览GitHub时 看到好多项目下面会有如下图标 几经折腾之后 发现这个一个非常好用的VS插件 称为神级也不为过 可以进行编写提示 代码重构 文件搜索等许多操作 当然目前最新版的VS中已经具有很多类似的功能 但是这个插件从实用性上来说
  • 2014年2月7日星期五(7-3,消除了背面的3D线框立方体)

    好久没进行了 看看吧 与DEMO7 2的区别 只看不同的地方 相机类型不同 归一化平面改为2 2 ar 视口为640 480 执行了背面消除 就是判断面元向量与面元到视点向量的点乘 gt 0 则可见 否则 消除 这一步是在物体剔除后和世界坐
  • 百度飞浆零基础实践深度学习入门课,通过PaddlePaddle实现波士顿房价预测

    百度架构师手把手带你零基础实践深度学习 课程已加入学习 对深度学习有了深入浅出对理解 并通过两种方式实现波士顿房价预测的算法 包括Python和Numpy构建深度学习框架 以及使用paddlepaddle快速搭建 快速实现预测 A 使用Py
  • 使用pl.droidsonroids.gif.GifImageView在安卓中显示动图遇到的问题

    在做一款聊天软件 其中聊天界面需要发送表情 而表情都是动图 在安卓中想要显示动图 就要借助第三方框架 我选的是pl droidsonroids gif GifImageView 使用方法如下 你在github上下载了android gif
  • Webpack5 处理图片资源、图标资源、修改输出目录、清空上一次打包的所有文件

    1 处理图片资源 Webpack5 已经将两个 Loader file loader 和 url loader 功能内置到 Webpack 里了 我们只需要简单配置即可处理图片资源 优化 gt 小图片转化为base64 小图片可以转换为ba
  • android分析monkey的anr

    1 根据anr信息和traces txt判断anr是发生在那个进程中 2 在文件夹logs4android x中搜索 ANR 或者在monkeylog中搜索 anr in 找到发生anr的时间 3 在文件夹logs4android x中搜索
  • 基于深度路由的水下传感器网络(翻译、整理)

    基于深度路由的水下传感器网络 翻译 整理 背景与意义 无线传感器网络引起了研究人员的广泛关注 并在该领域取得了很大进展 起初 这些网络仅涵盖地面的实用程序 但后来 由于在地球被 70 水覆盖 所以大家开始研究传感器网络的水下应用 也就是我们
  • 超声非线性成像-谐波成像基本知识

    文章目录 概述 超声的非线性 组织谐波成像 组织谐波的提取方法 组织谐波成像的优点 造影谐波成像 应用实例 总结 参考文献 概述 最近了解了一下非线性超声中的谐波成像 可以作为知识普及了解一下 大部分来自于文献 如有遗漏可以私信咸鱼进行修改
  • 可重入锁是什么?

    本文内容如有错误 不足之处 欢迎技术爱好者们一同探讨 在本文下面讨论区留言 感谢 文章目录 简介 ReentrantLock 中断锁获取 可重入设计的意义 不可重入锁 不可重入改为可重入 简介 可重入锁在Java中有synchronize和
  • 麒麟服务器系统、CentOS系统扩展磁盘、根目录大小

    一 实际问题 服务器根目录占用53 只有13G可用 需要扩容磁盘 若没有单独分区给目录做存储 其他目录如 var lib 都是默认共享根目录空间大小的 若这些目录空间太小都可以通过扩容根目录大小解决 二 介绍部分 介绍 PV VG LV P
  • Set(List)与String互转

    一 Set与String互转 在处理JSON数据时 我发现想把数据取出来用set去重 然后toString后放回JSON 但是再取出来要转成Set时就出问题了 这是一个用例 JSONObject jsonObject new JSONObj
  • 【c++从菜鸡到王者】第五篇-( 全网最精华)条件编译ifdef的用法

    预处理指令 预处理指令是以 号开头的代码行 号必须是该行除了任何空白字符外的第一个字符 后是指令关键字 在关键字和 号之间允许存在任意个数的空白字符 整行语句构成了一条预处理指令 该指令将在编译器进行编译之前对源代码做某些转换 预处理指令是
  • Qt QTouchEvent 多点触控

    首先设置接收触控事件 setAttribute Qt WA AcceptTouchEvents true bool CollectionPoint event QEvent event switch event gt type case Q
  • 一,Docker安装与启动

    目录 1 安装Docker 2 设置ustc的镜像 3 Docker的启动与停止 3 常用命令 3 1 1 查看镜像 3 1 2 搜索镜像 3 1 3 拉取镜像 3 1 4 删除镜像 3 2 容器相关命令 3 2 1 查看容器 3 2 2
  • 包建强:为什么我说Android插件化从入门到放弃?

    转自 http www infoq com cn articles android plug ins from entry to give up 本文根据包建强在2016GMTC全球移动开发大会上的演讲整理而成 首先自我介绍一下 我叫包建强
  • 【c++】rand()随机函数的应用(一)——rand()函数详解和实例

    c 语言中可以用rand 函数生成随机数 今天来探讨一下rand 函数的基本用法和实际应用 本系列文章共分两讲 今天主要介绍一下伪随机数生成的原理 以及在伪随机数生成的基础上 生成随机数的技巧 下一讲主要介绍无重复随机数生成的方法和舒尔特方