C++ 中的随机数生成全方面介绍

目录

引言

基本概念

什么是随机数?

伪随机数生成器(PRNG)

线性同余生成器(LCG)

梅尔森旋转算法(Mersenne Twister)

随机数的质量

随机数生成器的测试

C++ 中的随机数生成

传统方法:rand() 和 srand()

rand()

srand()

新标准库:

随机数引擎

分布

生成随机数的步骤

示例:生成随机数

生成 1 到 100 之间的随机整数

生成 0 到 1 之间的随机浮点数

进阶技巧

多线程中的随机数生成

性能优化

常见问题

生成的随机数总是相同的

随机数生成器的种子

高级主题

随机数生成的质量

随机数生成器的测试

随机数生成器的并行化

实际应用

游戏开发中的随机数生成

模拟中的随机数生成

总结


引言

在编程中,随机数生成是一个非常常见的需求,尤其是在游戏开发、模拟、加密等领域。C++ 提供了多种生成随机数的方法,从简单的标准库函数到复杂的随机数生成器类。本文将全面介绍 C++ 中的随机数生成技术,包括基本概念、实现方法、代码示例和进阶技巧。本文将尽量详细地涵盖每一个细节,力求让读者对 C++ 中的随机数生成有全面而深入的理解。

基本概念

什么是随机数?

随机数是指在一个特定范围内,按照某种概率分布生成的数。在计算机中,真正的随机数很难生成,通常使用伪随机数生成器(Pseudo-Random Number Generator, PRNG)来近似实现。

伪随机数生成器(PRNG)

伪随机数生成器通过一个初始值(称为种子)和一系列算法来生成一系列看似随机的数。常见的 PRNG 算法包括线性同余生成器(Linear Congruential Generator, LCG)和梅尔森旋转算法(Mersenne Twister)。

线性同余生成器(LCG)

线性同余生成器是一种简单的 PRNG,其生成公式如下:

[ X_{n+1} = (aX_n + c) \mod m ]

其中:

  • ( X_n ) 是第 ( n ) 个随机数。
  • ( a ) 是乘数。
  • ( c ) 是增量。
  • ( m ) 是模数。

LCG 的优点是实现简单,计算速度快,但生成的随机数序列的周期较短,且容易出现模式。

梅尔森旋转算法(Mersenne Twister)

梅尔森旋转算法是一种高效的 PRNG,其周期非常长(例如 ( 2^{19937} - 1 )),且生成的随机数质量较高。Mersenne Twister 的实现较为复杂,但 C++11 的 <random> 库中已经提供了 std::mt19937 类,方便开发者使用。

随机数的质量

随机数的质量是一个重要的考虑因素。一个好的随机数生成器应该生成的数列具有以下特性:

  • 均匀性:生成的数在指定范围内均匀分布。
  • 独立性:生成的数之间相互独立。
  • 周期性:生成的数列的周期足够长,以避免重复。

随机数生成器的测试

为了评估随机数生成器的质量,可以使用一些标准的测试方法,如:

  • 频数测试:检查生成的数在指定范围内是否均匀分布。
  • 序列测试:检查生成的数列是否具有独立性。
  • 游程测试:检查生成的数列中的游程长度是否符合预期。

C++ 中的随机数生成

传统方法:rand() 和 srand()

C++ 中最简单的随机数生成方法是使用 rand() 和 srand() 函数。这些函数位于 <cstdlib> 头文件中。

rand()

rand() 函数生成一个在 0 到 RAND_MAX 之间的随机整数。RAND_MAX 是一个常量,通常定义为 32767

#include <cstdlib>
#include <iostream>int main() {int random_number = rand();std::cout << "Random number: " << random_number << std::endl;return 0;
}
srand()

srand() 函数用于设置随机数生成器的种子。如果不设置种子,rand() 会生成相同的随机数序列。

#include <cstdlib>
#include <ctime>
#include <iostream>int main() {srand(time(0));  // 使用当前时间作为种子int random_number = rand();std::cout << "Random number: " << random_number << std::endl;return 0;
}

新标准库:<random>

C++11 引入了新的随机数生成库 <random>,提供了更强大和灵活的随机数生成工具。

随机数引擎

随机数引擎是生成随机数的核心类。常见的随机数引擎包括:

  • std::default_random_engine
  • std::mt19937(梅尔森旋转算法)
  • std::linear_congruential_engine(线性同余生成器)
分布

分布类用于定义随机数的分布。常见的分布类包括:

  • std::uniform_int_distribution(均匀分布整数)
  • std::uniform_real_distribution(均匀分布浮点数)
  • std::normal_distribution(正态分布)
  • std::binomial_distribution(二项分布)
  • std::poisson_distribution(泊松分布)
  • std::exponential_distribution(指数分布)
  • std::gamma_distribution(伽玛分布)
  • std::weibull_distribution(威布尔分布)
  • std::extreme_value_distribution(极值分布)
生成随机数的步骤
  1. 选择一个随机数引擎。
  2. 选择一个分布类。
  3. 生成随机数。
    #include <iostream>
    #include <random>
    #include <chrono>int main() {// 1. 选择一个随机数引擎std::mt19937 engine(std::chrono::system_clock::now().time_since_epoch().count());// 2. 选择一个分布类std::uniform_int_distribution<int> distribution(1, 100);// 3. 生成随机数int random_number = distribution(engine);std::cout << "Random number: " << random_number << std::endl;return 0;
    }

示例:生成随机数

生成 1 到 100 之间的随机整数
#include <iostream>
#include <random>
#include <chrono>int main() {// 随机数引擎std::mt19937 engine(std::chrono::system_clock::now().time_since_epoch().count());// 均匀分布std::uniform_int_distribution<int> distribution(1, 100);// 生成随机数int random_number = distribution(engine);std::cout << "Random number: " << random_number << std::endl;return 0;
}
生成 0 到 1 之间的随机浮点数
#include <iostream>
#include <random>
#include <chrono>int main() {// 随机数引擎std::mt19937 engine(std::chrono::system_clock::now().time_since_epoch().count());// 均匀分布std::uniform_real_distribution<double> distribution(0.0, 1.0);// 生成随机数double random_number = distribution(engine);std::cout << "Random number: " << random_number << std::endl;return 0;
}

进阶技巧

多线程中的随机数生成

在多线程环境中,使用同一个随机数引擎可能会导致线程安全问题。为了避免这种情况,可以为每个线程创建一个独立的随机数引擎。

#include <iostream>
#include <random>
#include <chrono>
#include <thread>
#include <vector>void generate_random_numbers(std::mt19937 &engine) {std::uniform_int_distribution<int> distribution(1, 100);for (int i = 0; i < 10; ++i) {int random_number = distribution(engine);std::cout << "Thread " << std::this_thread::get_id() << ": " << random_number << std::endl;}
}int main() {std::vector<std::thread> threads;std::mt19937 engine(std::chrono::system_clock::now().time_since_epoch().count());for (int i = 0; i < 5; ++i) {std::mt19937 thread_engine(engine());threads.emplace_back(generate_random_numbers, std::ref(thread_engine));}for (auto &t : threads) {t.join();}return 0;
}
性能优化

在高性能应用中,随机数生成的性能是一个重要的考虑因素。以下是一些优化技巧:

  • 使用更高效的随机数引擎:例如 std::mt19937
  • 避免频繁重新初始化随机数引擎:初始化随机数引擎是一个相对昂贵的操作。
  • 使用预生成的随机数池:如果需要大量随机数,可以预先生成一个随机数池,然后从中取数。

常见问题

生成的随机数总是相同的

如果你发现生成的随机数总是相同的,可能是因为没有正确设置随机数生成器的种子。确保在每次运行程序时使用不同的种子,例如当前时间。

#include <iostream>
#include <cstdlib>
#include <ctime>int main() {srand(time(0));  // 使用当前时间作为种子int random_number = rand();std::cout << "Random number: " << random_number << std::endl;return 0;
}
随机数生成器的种子

随机数生成器的种子是一个初始值,用于生成随机数序列。不同的种子会导致不同的随机数序列。通常使用当前时间作为种子。

#include <iostream>
#include <cstdlib>
#include <ctime>int main() {srand(time(0));  // 使用当前时间作为种子int random_number = rand();std::cout << "Random number: " << random_number << std::endl;return 0;
}

高级主题

随机数生成的质量

随机数生成的质量是一个重要的考虑因素。一个好的随机数生成器应该生成的数列具有以下特性:

  • 均匀性:生成的数在指定范围内均匀分布。
  • 独立性:生成的数之间相互独立。
  • 周期性:生成的数列的周期足够长,以避免重复。
随机数生成器的测试

为了评估随机数生成器的质量,可以使用一些标准的测试方法,如:

  • 频数测试:检查生成的数在指定范围内是否均匀分布。
  • 序列测试:检查生成的数列是否具有独立性。
  • 游程测试:检查生成的数列中的游程长度是否符合预期。
随机数生成器的并行化

在多核或多线程环境中,随机数生成器的并行化是一个重要的问题。常见的并行化方法包括:

  • 共享种子:所有线程共享同一个种子,但使用不同的随机数引擎。
  • 独立种子:每个线程使用不同的种子,生成独立的随机数序列。

实际应用

游戏开发中的随机数生成

在游戏开发中,随机数生成器用于生成各种随机事件,如敌人的位置、掉落的物品、玩家的属性等。使用高质量的随机数生成器可以提高游戏的可玩性和公平性。

#include <iostream>
#include <random>
#include <chrono>class Enemy {
public:Enemy(int x, int y) : x_(x), y_(y) {}void print_position() const {std::cout << "Enemy position: (" << x_ << ", " << y_ << ")" << std::endl;}private:int x_;int y_;
};int main() {std::mt19937 engine(std::chrono::system_clock::now().time_since_epoch().count());std::uniform_int_distribution<int> x_distribution(0, 100);std::uniform_int_distribution<int> y_distribution(0, 100);Enemy enemy(x_distribution(engine), y_distribution(engine));enemy.print_position();return 0;
}
模拟中的随机数生成

在模拟中,随机数生成器用于生成各种随机事件,如天气变化、交通流量、股票价格等。使用高质量的随机数生成器可以提高模拟的准确性和可靠性。

#include <iostream>
#include <random>
#include <chrono>class WeatherSimulator {
public:WeatherSimulator() : engine_(std::chrono::system_clock::now().time_since_epoch().count()) {}void simulate_weather() {std::uniform_int_distribution<int> temperature_distribution(-20, 40);std::uniform_int_distribution<int> precipitation_distribution(0, 100);int temperature = temperature_distribution(engine_);int precipitation = precipitation_distribution(engine_);std::cout << "Temperature: " << temperature << "°C, Precipitation: " << precipitation << "%" << std::endl;}private:std::mt19937 engine_;
};int main() {WeatherSimulator simulator;simulator.simulate_weather();return 0;
}

总结

C++ 提供了多种生成随机数的方法,从简单的 rand() 和 srand() 到强大的 <random> 库。选择合适的方法和工具,可以让你的程序更加灵活和高效。希望本文对您理解 C++ 中的随机数生成有所帮助。

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

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

相关文章

Django实现智能问答助手-数据库方式读取问题和答案

扩展 增加问答数据库&#xff0c;通过 Django Admin 添加问题和答案。实现更复杂的问答逻辑&#xff0c;比如使用自然语言处理&#xff08;NLP&#xff09;库。使用前端框架&#xff08;如 Bootstrap&#xff09;增强用户界面 1.注册模型到 Django Admin&#xff08;admin.py…

问:Spring Boot应用监控组件工具,梳理一下?

在日常运维与开发过程中&#xff0c;Spring Boot 应用的监控是确保系统稳定性和性能的关键环节。本文将探讨 Spring Boot 常用的监控组件及工具的原理、适用场景&#xff0c;并针对不同场景下的运维监控方案进行介绍。 1. Spring Boot Actuator 原理&#xff1a; Spring Boo…

Spring-02-springmvc

2. 什么是SpringMVC 2.1. 概述 Spring MVC是Spring Framework的一部分&#xff0c;是基于Java实现MVC的轻量级Web框架。 为什么要学习SpringMVC呢? Spring MVC的特点&#xff1a; 轻量级&#xff0c;简单易学高效 , 基于请求响应的MVC框架与Spring兼容性好&#xff0c;无缝…

【数据结构】【线性表】一文讲完队列(附C语言源码)

队列 队列的基本概念基本术语基本操作 队列的顺序实现顺序队列结构体的创建顺序队列的初始化顺序队列入队顺序队列出队顺序队列存在的问题分析循环队列代码汇总 队列的链式实现链式队列的创建链式队列初始化-不带头结点链式队列入队-不带头节点链式队列出队-不带头结点带头结点…

cf 988 div3 C 将一些特定的元素拿出来考虑 E(交互,考虑多询问一位,以此判断这一位的情况)

C题意&#xff1a; [1 n] 的排列&#xff0c;我们要任意相邻的数相加得到的和是合数。 如果对于n 不存在这个一个排列&#xff0c;那么输出-1 一个比较显然的思路 就是奇数放一起&#xff0c;偶数放一起。奇数之间相加是偶数 偶数之间相加是偶数。那么他们都是合数。 但是还有…

手机文件可以打印出来吗

在数字化时代&#xff0c;手机已成为我们日常生活和工作中不可或缺的一部分。很多时候&#xff0c;我们需要将手机上的文件打印出来&#xff0c;无论是学习资料、工作报告还是生活文档。那么&#xff0c;手机上的文件真的可以打印出来吗&#xff1f;答案是肯定的。 直接前往打…

《Spring Boot:快速构建应用的利器》

一、Spring Boot 的崛起与优势 &#xff08;四&#xff09;丰富的生态支持 Spring Boot 拥有强大的生态系统&#xff0c;这是它在 Java 开发领域中占据重要地位的关键因素之一。 Spring Cloud 是 Spring Boot 生态中的重要组成部分&#xff0c;它为构建分布式系统的微服务架构…

爬虫实战:采集知乎XXX话题数据

目录 反爬虫的本意和其带来的挑战目标实战开发准备代码开发发现问题1. 发现问题[01]2. 发现问题[02] 解决问题1. 解决问题[01]2. 解决问题[02] 最终结果 结语 反爬虫的本意和其带来的挑战 在这个数字化时代社交媒体已经成为人们表达观点的重要渠道&#xff0c;对企业来说&…

微信小程序2-地图显示和地图标记

一、index修改页面&#xff0c;让页面能够显示地图和一个添加标记的按钮。 index.wxml <scroll-view class"scrollarea" scroll-y type"list"><view class"index_container"><map id"map" style"width: 100%; h…

Qt入门1——认识Qt的几个常用头文件和常用函数

1.头文件 ① #include <QPushButton>——“按钮”头文件&#xff1b; ② #include <QLabel>——“标签”头文件&#xff1b; ③ #include <QFont>——“字体”头文件&#xff1b; ④#include <QDebug>——输出相关信息&#xff1b; 2. 常用函数/类的基…

【vue3+Typescript】unapp+stompsj模式下替代plus-websocket的封装模块

由于plus-websocket实测存在消息丢失的问题&#xff0c;只能寻找替代的方案&#xff0c;看文章说使用原生的即可很好的工作。而目前在stompjs里需要使用websocket类型的封装模块&#xff0c;看了下原来提供的接口&#xff0c;采用uniapp原生的websocket模式&#xff0c;对原模块…

社交电商专业赋能高校教育与产业协同发展:定制开发AI智能名片及2+1链动商城小程序的创新驱动

摘要&#xff1a;本文围绕社交电商有望成为高校常态专业这一趋势展开深入探讨&#xff0c;剖析国家政策认可下其学科发展前景&#xff0c;着重阐述在专业建设进程中面临的师资短缺及实践教学难题。通过引入定制开发AI智能名片与21链动商城小程序&#xff0c;探究如何借助这些新…

Linux进阶:环境变量

环境变量是一组信息记录&#xff0c;类型是KeyValue型&#xff08;名值&#xff09;&#xff0c;用于操作系统运行的时候记录关键信息. env命令&#xff1a;查看系统全部的环境变量 语法&#xff1a;env $符号&#xff1a;取出指定的环境变量的值 语法&#xff1a;$变量名 …

CPU命名那些事

一、Intel CPU命名 1. 命名结构 Intel CPU 的命名通常包含以下几个部分&#xff1a; 品牌 产品线 系列 代数 具体型号 后缀 例如&#xff1a;Intel Core i7-13700K 2. 各部分含义 品牌 Intel&#xff1a;表示厂商&#xff08;几乎所有命名中都有&#xff09;。不同品…

英语写作中“联系、关联”associate correlate 及associated的用法

似乎是同义词的associate correlate 实际上意思差别明显&#xff0c;associate 是人们把两者联系在一起&#xff08;主观联系&#xff09;&#xff0c;而correlate 指客观联系。 例如&#xff1a; We always associate sports with health.&#xff08;我们总是将运动和健康联…

AR智能眼镜|AR眼镜定制开发|工业AR眼镜方案

AR眼镜的设计与制造成本主要受到芯片、显示屏和光学方案的影响&#xff0c;因此选择合适的芯片至关重要。一款优秀的芯片平台能够有效提升设备性能&#xff0c;并解决多种技术挑战。例如&#xff0c;采用联发科八核2.0GHz处理器&#xff0c;结合12nm制程工艺&#xff0c;这种低…

Unity 设计模式-单例模式(Singleton)详解

设计模式 设计模式 是指在软件开发中为解决常见问题而总结出的一套 可复用的解决方案。这些模式是经过长期实践证明有效的 编程经验总结&#xff0c;并可以在不同的项目中复用。设计模式并不是代码片段&#xff0c;而是对常见问题的 抽象解决方案&#xff0c;它提供了代码结构…

第二十一周机器学习笔记:动手深度学习之——数据操作、数据预处理

第二十周周报 摘要Abstract一、动手深度学习1. 数据操作1.1 数据基本操作1.2 数据运算1.2.1 广播机制 1.3 索引和切片 2. 数据预处理 二、复习RNN与LSTM1. Recurrent Neural Network&#xff08;RNN&#xff0c;循环神经网络&#xff09;1.1 词汇vector的编码方式1.2 RNN的变形…

ThinkPad t61p 作SMB服务器,打印服务器,pc ,android ,ipad利用此服务器互传文件

1.在t61p上安装win7 2,配置好smb 服务 3.再安装好打印驱动程序 4.pc与win7利用系统的网络互相发现,映射为硬盘使用。 5.android&#xff0c;ipad安装ES文件浏览器访问win7 共享文件夹&#xff0c;互传文件。 6.android手机安装FE文件浏览器&#xff0c;可以利用花生壳外网…

【深度学习之二】正则化函数(weight decay, dropout, label smoothing, and etc)详解,以及不同的函数适用的场景

在深度学习中正则化函数的重要性不言而喻&#xff0c;今天主要总结一些当前常用的一些正则化函数 在深度学习中&#xff0c;正则化&#xff08;Regularization&#xff09;是一种防止模型过拟合的技术。过拟合指的是模型在训练数据上表现很好&#xff0c;但在未见过的测试数据…