C++ 中的 std::exponential_distribution

2025年5月19日 | 阅读 7 分钟

引言

本文的主要主题是 C++ 中的 std::exponential_distribution 类,它是标准库中一个非常有用的工具,用于生成具有指数分布的随机数。这种分布在泊松过程中事件之间的时间引起关注时会用到,例如在排队论、可靠性工程和生存分析中。

在本文中,我们将探讨 std::exponential_distribution 类、它的工作原理以及它在实际问题中的使用。

指数分布

指数分布是一种连续随机变量的分布,适用于模拟泊松过程中事件之间的时间。它只用一个参数 λ 来描述,该参数是速率参数。

f(x;λ)=λe-λx

其中,

  • x = 代表时间的随机变量
  • λ = 速率参数。

必要的头文件

如果我们要使用 std::exponential_distribution,则需要包含 <random> 头文件。此头文件提供了随机数生成所需的类和函数。

创建指数分布

我们可以使用默认构造函数或随机引擎的参数化构造函数来创建 std::exponential_distribution 实例。

1. 默认构造器

  • 以默认速率参数 λ=1.0 开始分布

2. 参数化构造函数

  • 使我们能够设置发生率 λ 的参数。

关于 Random 头文件

<random> 头文件是 C++ 标准库的一个组件,已集成到 C++11 语言中。例如,它提供了一组用于生成随机数并对其执行一般操作的函数。例如,有一个用于创建随机数生成器的类,以及用于使用所述数字的某些分布以及用于管理随机数生成器类型的类。

Random 头文件的组成部分

1. 随机数引擎

一些示例是:

  • 线性同余生成器 - std::minstd_rand0, std::minstd_rand
  • 减法随机数生成器 - std::ranlux24_base, std::ranlux48_base, std::ranlux24, std::ranlux48

2. 随机数分布

一些示例是:

  • 整数值的均匀分布 - std::uniform_int_distribution
  • 浮点值的均匀分布 - std::uniform_real_distribution: 布尔分布 (true/false) - Bernoulli 分布允许的三个参数是:
  • 其他特殊分布 - std::extreme_value_distribution (基于分析中检测到的极端事件生成极值分布)。

3. 概率泛化和非确定性生成

一些示例是:

  • 提供对非确定性随机数的访问(如果可用) - std::random_device

4. 其他实用程序

一些示例是:

  • 用于初始化随机数引擎的种子值序列 - std::seed_seq

Random 头文件示例 1

问题陈述: 生成均匀分布的随机数

输出 1

30 40 15 23 31 
=== Code Execution Successful ===

输出 2

2 30 10 26 30 
=== Code Execution Successful ===

代码解释

1. 初始化

2. 分布定义

这会创建一个均匀分布,以生成介于 1 和 50 之间的整数。

3. 生成数字

一个循环从定义的分布中生成并打印五个随机整数。

Random 头文件示例 2

问题陈述: 用指数分布模拟网络数据包到达

输出

Packet 1 arrived at 2.647 with size 549.662 bytes.
Packet 2 arrived at 6.968 with size 392.527 bytes.
Packet 3 arrived at 8.1762 with size 446.382 bytes.
Packet 4 arrived at 12.1417 with size 422.995 bytes.
Packet 5 arrived at 12.8545 with size 406.127 bytes.
Packet 6 arrived at 13.187 with size 514.723 bytes.
Packet 7 arrived at 15.2886 with size 413.032 bytes.
Packet 8 arrived at 16.0074 with size 487.628 bytes.
Packet 9 arrived at 17.4922 with size 520.079 bytes.
Packet 10 arrived at 19.9851 with size 448.265 bytes.
Packet 11 arrived at 26.9368 with size 458.188 bytes.
Packet 12 arrived at 29.2227 with size 498.873 bytes.
Packet 13 arrived at 29.3468 with size 451.223 bytes.
Packet 14 arrived at 31.1982 with size 475.573 bytes.
Packet 15 arrived at 32.1214 with size 509.195 bytes.
Packet 16 arrived at 33.9577 with size 362.997 bytes.
Packet 17 arrived at 34.5125 with size 565.237 bytes.
Packet 18 arrived at 36.897 with size 483.421 bytes.
Packet 19 arrived at 40.8254 with size 482.831 bytes.
Packet 20 arrived at 40.9058 with size 505.229 bytes.
Packet 21 arrived at 41.9937 with size 439.408 bytes.
Packet 22 arrived at 43.3056 with size 488.416 bytes.
Packet 23 arrived at 43.9117 with size 586.987 bytes.
Packet 24 arrived at 45.6715 with size 531.251 bytes.
Packet 25 arrived at 46.9939 with size 368.973 bytes.
Packet 26 arrived at 52.3196 with size 439.729 bytes.
Packet 27 arrived at 53.1564 with size 447.493 bytes.
Packet 28 arrived at 53.3603 with size 523.402 bytes.
Packet 29 arrived at 53.479 with size 472.463 bytes.
Packet 30 arrived at 60.5505 with size 511.338 bytes.
Total packets: 30
Average inter-arrival time: 2.01835 time units
Average packet size: 473.455 bytes
Maximum packet size: 586.987 bytes

=== Code Execution Successful ===

说明

1. 模拟参数

这些常量定义了模拟:arrival_rate 指定了平均数据包到达率,size_mean 和 size_stddev 定义了数据包大小的平均值和标准差,num_packets 是要模拟的数据包数量。

2. 随机数生成

在这里,我们为随机数生成器的创建做准备。std::random_device 用于为 Mersenne Twister 引擎(也称为 std::mt19937)设定种子。arrival_dist 字段生成到达间隔时间,size_dist 创建数据包大小。

3. 数据包生成

为了创建 num_packets 个数据包,形成一个循环。对于每个数据包,它计算到达间隔时间,然后将此值添加到当前时间,确定数据包大小,并确保它大于零。之后,它将数据包存储在一个向量中,然后打印其详细信息。

4. 统计计算

这包括使用标准库算法计算的总到达间隔时间、总数据包大小、数据包之间的平均到达间隔时间、平均数据包大小以及从接收到的数据包中最大的数据包大小。

5. 统计输出

它在控制台上打印出一些模拟数据包的统计结果。