生成特定分布随机数的方法

article/2025/11/11 0:02:44

生成随机数是程序设计里常见的需求。一般的编程语言都会自带一个随机数生成函数,用于生成服从均匀分布的随机数。不过有时需要生成服从其它分布的随机数,例如高斯分布或指数分布等。有些编程语言已经有比较完善的实现,例如Python的NumPy。这篇文章介绍如何通过均匀分布随机数生成函数生成符合特定概率分布的随机数,主要介绍Inverse Ttransform和Acceptance-Rejection两种基础算法以及一些相关的衍生方法。下文我们均假设已经拥有一个可以生成0到1之间均匀分布的随机数生成函数,关于如何生成均匀分布等更底层的随机数生成理论,请参考其它资料,本文不做讨论。

  • 基础算法
    • Inverse Transform Method
      • ITM算法描述
      • ITM算法说明
      • ITM实现示例
    • Acceptance-Rejection Method
      • ARM算法描述
      • ARM算法说明
      • ARM实现示例
  • 衍生算法
    • 组合算法
    • 生成具有相关性的随机数
  • 更多参考

基础算法

Inverse Transform Method

最简单的生成算法是Inverse Transform Method(下文简称ITM)。如果我们可以给出概率分布的累积分布函数(下文简称CDF)及其逆函数的解析表达式,则可以非常简单便捷的生成指定分布随机数。

ITM算法描述

  1. 生成一个服从均匀分布的随机数UUni(0,1)
  2. F(X)为指定分布的CDF,F1(Y)是其逆函数。返回X=F1(U)作为结果

ITM算法说明

这是一个非常简洁高效的算法,下面说明其原理及正确性。

我们通过图示可以更直观的明白算法的原理。下图是某概率分布的CDF:

我们从横轴上标注两点xaxb,其CDF值分别为F(xa)F(xb)

由于U服从0到1之间的均匀分布,因此对于一次U的取样,U落入F(xa)F(xb)之间的概率为:

P(U(F(xa),F(xb)))=F(xb)F(xa)

而由于CDF都是单调非减函数,因此这个概率同时等于X落入xaxb之间的概率,即:

P(U(F(xa),F(xb)))=P(F1(U)(F1(F(xa)),F1(F(xb))))=P(X(xa,xb))=F(xb)F(xa)

而根据CDF的定义,这刚好说明X服从以F(x)为CDF的分布,因此我们的生成算法是正确的。

ITM实现示例

下面以指数分布为例说明如何应用ITM。

首先我们需要求解CDF的逆函数。我们知道指数分布的CDF为

F(X)=1eλX

通过简单的代数运算,可以得到其逆函数为

F1(Y)=1λln(1Y)

由于U服从从0到1的均匀分布蕴含着1U服从同样的分布,因此在实际实现时可以用Y代替1Y,得到:

F1(Y)=1λln(Y)

下面给出一个Python的实现示例程序。

  1. import random
  2. import math
  3. def exponential_rand(lam):
  4. if lam <= 0:
  5. return -1
  6. U = random.uniform(0.0, 1.0)
  7. return (-1.0 / lam) * math.log(U)

Acceptance-Rejection Method

一般来说ITM是一种很好的算法,简单且高效,如果可以使用的话,是第一选择。但是ITM有自身的局限性,就是要求必须能给出CDF逆函数的解析表达式,有些时候要做到这点比较困难,这限制了ITM的适用范围。

当无法给出CDF逆函数的解析表达式时,Acceptance-Rejection Method(下文简称ARM)是另外的选择。ARM的适用范围比ITM要大,只要给出概率密度函数(下文简称PDF)的解析表达式即可,而大多数常用分布的PDF是可以查到的。

ARM算法描述

  1. 设PDF为f(x)。首先生成一个均匀分布随机数XUni(xmin,xmax)
  2. 独立的生成另一个均匀分布随机数YUni(ymin,ymax)
  3. 如果Yf(X),则返回X,否则回到第1步

ARM算法说明

通过一幅图可以清楚的看到ARM的工作原理。

ARM本质上是一种模拟方法,而非直接数学方法。它每次生成新的随机数后,通过另一个随机数来保证其被接受概率服从指定的PDF。

显然ARM从效率上不如ITM,但是其适应性更广,在无法得到CDF的逆函数时,ARM是不错的选择。

ARM实现示例

下面使用ARM实现一个能产生标准正态分布的随机数生成函数。

首先我们要得到标准正态分布的PDF,其数学表示为:

f(x)=12πex22

为了方便,这里我会直接使用SciPy来计算其PDF。

程序如下。

  1. import random
  2. import scipy.stats as ss
  3.  
  4. def standard_normal_rand():
  5. while True:
  6. X = random.uniform(-3.0,3.0)
  7. Y = random.uniform(0.0, 0.5)
  8. if Y < ss.norm.pdf(X):
  9. return X

注意:标准正态分布的x取值范围从理论上说是(,),但是当离开均值点很远后,其概率密度可忽略不计。这里只取(3.0,3.0),实际使用时可以根据具体需要扩大这个取值范围。

衍生算法

组合算法

当目标分布可以用其它分布经过四则运算表示时,可以使用组合算法生成对应随机数。

最常见的就是某分布可以表示成多个独立同分布(下文简称IID)随机变量之和。例如二项分布可以表示成多个0-1分布之和,Erlang分布可以由多个IID的指数分布得出。

以Erlang分布为例说明如何生成这类随机数。

X1,X2,,Xk为服从0到1均匀分布的IID随机数,则1λlnX1,1λlnX2,,1λlnXk为服从指数分布的IID随机数,因此

X=1λlnX11λlnX21λlnXk=1λlnki=1XiErl(k,λ)

所以生成Erlang分布随机数的算法如下:

  1. 生成X1,X2,,XkUni(0,1)
  2. 返回1λlnki=1Xi

这类分布的随机数生成算法很直观,就是先生成相关的n个IID随机数,然后带入简单求和公式或其它四则公式得出最终随机数。其数学理论基础是卷积理论,稍微有些复杂,这里不再讨论,有兴趣的同学可以查阅相关资料。

生成具有相关性的随机数

现在考虑生成多维随机数,以最简单的二维随机数为例。

如果两个维度的随机数是相互独立的,那么只要分别生成两个列就可以了。但是如果要求两列具有一定的相关系数,则需要做一些特殊处理。

下列算法可以生成两列具有相关系数ρ的随机数。

  1. 生成IID随机变量XY
  2. 计算X=ρX+1ρ2Y
  3. 返回(X,X)

可以这样验证其正确性:

corr(X,X)=ρcorr(X,X)+1ρ2corr(X,Y)=ρ

注意corr(X,X)=1corr(X,Y)=0

因此XX确实具有相关系数ρ

更多参考

这篇文章讨论了生成指定分布随机数的基本方法。这篇文章只打算讨论基础方法,所以还有很多有趣的内容,本文没有深入的探讨。这里给出一些扩展阅读资料,供有兴趣的朋友深入学习。首先是一篇非常好的文档,这篇文章来自美国陆军实验室,对计算机生成指定分布随机数的方方面面进行了全面深入描述,是不可多得的好资料。

在实现方面,可以参考NumPy中关于random的实现以及我开发的JavaScript实现。另外我做过一个不同概率分布的可视化页面,可以帮助你直观理解不同分布及PDF参数对分布的影响。


http://chatgpt.dhexx.cn/article/QaBKx1mq.shtml

相关文章

推导:通过均匀分布来产生任意分布随机数

最近想用C语言写一个产生服从指数分布的随机数的程序。从网上找了找&#xff0c;发现可以通过均匀分布来产生服从任意分布的随机数。然而&#xff0c;网上的推导不是很完善&#xff0c;我把自己的理解写在这里&#xff0c;有不严谨的地方请大家指正。 命题1&#xff1a;对一连续…

随机数生成(一):均匀分布

引言 许多应用中都需要用到随机数&#xff0c;如物理仿真、统计采样、密码学、博彩等。随机数一般可以通过两种方法得到。一种是基于物理现象由硬件产生。由此得到的随机数&#xff0c;在产生之前是不可预知的&#xff0c;因此&#xff0c;是真正的随机数。另一种是通过计算机算…

如何产生指定分布的随机数?

参考&#xff1a;https://www.cnblogs.com/xingshansi/p/6539319.html&#xff1b;    https://www.jianshu.com/p/3d30070932a8&#xff1b;    https://blog.csdn.net/pipisorry/article/details/50615652&#xff1b;    https://cosx.org/2015/06/generating-n…

一、三大基础随机分布与数学特征

一、三大基础随机分布 均匀、指数、正态 1、均匀分布 表示在相同长度间隔的分布概率是等可能的 其概率密度、均值、方差 2、指数分布 事件以恒定平均速度连续且独立地发生的过程(泊松过程中的事件之间的时间的概率分布) 其概率密度、均值、方差 3、正态分布 常见的连续概…

AttributeError:Can only use .str accessor with string values!

修改之前&#xff1a; 出现错误&#xff1a;意为matches不是字符串则使用此方法错误 修改方法&#xff1a; 将最后两行代码改为&#xff1a;

“ Can only use .str accessor with string values!”

“ Can only use .str accessor with string values&#xff01;” 出现错误 原代码 解决办法&#xff1a;

vue3报错‘get‘ on proxy: property ‘__accessor__‘ is a read-only and non-configurable data property on t

在使用arcgis地图时候 我把map对象存进了store里面共享数据 结果其他页面使用时候 给我甩了这样一个错误 get on proxy: property __accessor__ is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expe…

Access数据库是什么

数据是当今社会的命脉&#xff0c;因此自然而然地&#xff0c;很多注意力都集中在不同的数据库工具上。毕竟&#xff0c;如果用户有合适的工具&#xff0c;用户就有最有效的方法来处理当前的海量数据过剩问题&#xff0c;或许还能让整个过程变得更易于管理。为此&#xff0c;本…

【ERROR Error: No value accessor for form control with unspecified name attribute】

遇到问题&#xff1a; 控制台报错如下ERROR Error: No value accessor for form control with unspecified name attribute 解决&#xff1a; [(ngModel)]不能直接加在某些标签中 需要同时加ngDefaultControl

access是干什么的软件

Access是一款数据库应用开发工具软件&#xff0c;中文名:微软办公软件-关系数据库管理系统。 access安装包 Access是微软公司于1994年发布的微机数据库管理系统。作为一种功能强大的MIS系统开发工具&#xff0c;它具有界面友好、易学易用、开发简单、界面灵活等特点&#xff0…

Access数据库有什么用?该数据库有什么功能?

对于那些想寻找一个简单的数据库管理系统的用户来说&#xff0c;微软旗下的Access数据库也许是可以让其眼前一亮的工具。 数据库基本定义 Access是Microsoft 365套件工具随附的强大生产力工具&#xff0c;该工具允许用户创建以有组织的结构存储信息的自定义数据库&#xff0c;还…

@Accessors

Accessors 作用&#xff1a;存取器&#xff0c;用于配置getter和setter方法的生成结果 三个属性&#xff1a;fluent、chain、prefix 1、fluent&#xff1a;流畅的&#xff0c;设置为true&#xff0c;getter和setter方法的方法名都是基础属性名&#xff0c;且setter方法返回当前…

使用pandas对数据提取时报错,AttributeError: Can only use .str accessor with string values!

from pandas import DataFrame from pandas import read_excel df read_excel(ri_nuc.xls,sheet_nameSheet4) df.head() 运行结果如下图 df.电话.head().str.strip() 结果出现报错 AttributeError: Can only use .str accessor with string values! 这句话翻译成&#xf…

@Accessors 注解详解

??前言1. Accessors 源码2. Accessors 属性详解2.1 fluent 属性2.2 chain 属性2.3 prefix 属性 前言 在你的工作中&#xff0c;有时候可能会看到Accessors(chain true)这样的注解&#xff0c;他是 lombok 插件包中的一个注解&#xff0c;那么它是什么意思呢&#xff1f; 1.…

lombok里的@Accessors注解

lombok里的Accessors注解 Accessor的中文含义是存取器&#xff0c;Accessors用于配置getter和setter方法的生成结果。 有三个属性 fluent–一个布尔值。如果属实&#xff0c;对于吸气pepper只是pepper()&#xff0c;并且设置器pepper(T newValue)。此外&#xff0c;除非指定…

Linux系统函数之lseek函数

Linux系统函数之lseek函数 fseek与lseek的对比文件存放位置:示例代码:使用lseek函数拓展文件的长度 fseek与lseek的对比 标准C库的函数#include <stdio.h>int fseek(FILE *stream, long offset, int whence);Linux系统函数#include <sys/types.h>#include <uni…

六、Linux文件 - lseek函数

目录 1.lseek函数 2.lseek函数实战 2.1宏SEEK_CUR的用法 2.2宏SEEK_END的用法 3.Open函数实战 - O_APPEND的用法 4.Linux在库函数中寻找相应的宏定义 1.lseek函数 off_t lseek(int fd,off_t offset,int whence);光标的偏移量 fd:文件描述符offset:偏移量whence: SEEK_…

【Linux系统IO函数】lseek函数

Linux系统IO函数—lseek函数 1.1 lseek函数与标准C库的fseek函数 lseek函数对应标准C库中的fseek函数 查看标准C库中的fseek函数使用说明&#xff1a; &#xff08;shell输入&#xff09; man 3 fseekfseek函数&#xff1a; #include <stdio.h> int fseek(FILE *st…

Linux编程基础之lseek函数返回值

目录 前言lseek函数返回值实操证明书的原图总结 前言 操作系统&#xff1a;Fedora 头文件 <sys/types.h> , <unistd.h> lseek函数返回值 off_t oldpos(int fd,off_t dist,int base)当lseek执行成功时&#xff0c;它会返回最终以文件起始位置为起点的偏移位置。如…

linux的 lseek 函数

目录 回顾lseek函数 回顾 前面讲了往文件里面写入一个字符串 并且能够读写 强调了 读写不能同时进行。下面重新敲一下代码 写完成了 并且查看到结果 下面是读的部分 开始新的内容lseek函数 lseek&#xff1a;光标函数 函数原型 和参数 说明 简单理解 SEEK_SET: OFFEST 为…