Box-Muller 与 ziggurat
1. Ziggurat 算法与 Box-muller 算法的效率比较

2. Box-Muller
a. 一般形式 因函数调用较多,速度慢,当u接近0时存在数值稳定性问题
先假设。
用Box-Muller方法,随机抽出两个从均匀分布的数字
和
。然后
那和
都是正态分布的。
证明可用极坐标,请参考教科书中的Box-Muller方法。
另外使用反函数,先随机抽出一个从均匀分布的数字
,然后
那是正态分布的。
b.极坐标形式,速度快且有更好的数值鲁棒性
double pf_ran_gaussian(double sigma)
{
double x1, x2, w, r; do
{
do { r = drand48(); } while (r==0.0);
x1 = 2.0 * r - 1.0;
do { r = drand48(); } while (r==0.0);
x2 = 2.0 * r - 1.0;
w = x1*x1 + x2*x2;
} while(w > 1.0 || w == 0.0); return(sigma * x2 * sqrt(-2.0*log(w)/w));
}
3. zigurat 方法
Box–Muller 算法虽然非常快,但是由于用到了三角函数和对数函数,相对来说还是比较耗时的,如果想要更快一点有没有办法呢?
当然有,这就是 Ziggurat 算法,不仅可以用于快速生成正态分布,还可以生成指数分布等等。Ziggurat 算法的基本思想是利用拒绝采样,什么是拒绝采样呢?
拒绝采样(Rejection Sampling),有的时候也称接收 - 拒绝采样,使用场景是有些函数p(x)
太复杂在程序中没法直接采样,那么可以设定一个程序可抽样的分布q(x)比如正态分布等等,然后按照一定的方法拒绝某些样本,达到接近p(x)
分布的目的:

具体操作如下,设定一个方便抽样的函数 $q(x)$,以及一个常量 $k$,使得 $p(x)$ 总在 $kq(x)$ 的下方。(参考上图)
- x轴方向:从q(x)分布抽样得到a
 
- y轴方向:从均匀分布(0,kq(a))中抽样得到u
 
- 如果刚好落到灰色区域:u>p(a),拒绝;否则接受这次抽样
 
- 重复以上过程
 
证明过程就不细说了,知道怎么用就行了,感兴趣的可以看看这个文档
不过在高维的情况下,拒绝采样会出现两个问题,第一是合适的 $q$ 分布比较难以找到,第二是很难确定一个合理的 $k$ 值。这两个问题会造成图中灰色区域的面积变大,从而导致拒绝率很高,无用计算增加。
采用拒绝采样来生成正态分布,最简单直观的方法莫过于用均匀分布作为 $q(x)$,但是这样的话,矩形与正态分布曲线间的距离很大,就会出现刚才提到的问题,高效也就无从谈起了。

而 Ziggurat 算法高效的秘密在于构造了一个非常精妙的q(x),看下面这张图

我们用多个堆叠在一起的矩形,这样保证阴影部分(被拒绝部分)的始终较小,这样就非常高效了
简单对图作一个解释:
- 我们用
R[i]来表示一个矩形,R[i]的右边界为x[i],上边界为y[i]。S[i]表示一个分割,当i=0时,S[0]=R[0]+tail,其他情况S[i]==R[i] - 除了
R[0]以外,其他每个矩形面积相等,设为定值A。R[0]的面积 = A-tail的面积。这样保证从任何一个分割中抽样(x,y)的概率相等 - 当任意选定一个
R[i]在其中抽样(x,y),若x<x[i+1],y必然在曲线下方,满足条件,接受x;若x[i+1]<x<x[i],则还需要进一步判断。同样这里R[0]和tail中的样本需要进行特殊处理 - 这里为了方便解释,只用了几个矩形,在程序实现的时候,一般使用
128或256个矩形 
可以看出,为了提高效率,Ziggurat 算法中使用了许多技巧性的东西,这在其C代码实现中更加明显,使用了与运算和字节等各种小技巧,代码就不在这里贴了,感兴趣可以看看下面几个版本,C版本的追求的是极致的速度,每个矩形的边界已经提前计算好了。C#版本中的注释非常详细,Java版的基本与C#一致,但是效率一般。
4. 总结
Box-muller 算法应对一般的需求足够了,但是要生成大量服从正态分布的随机数时,Ziggurat 算法效率会更高一点。
参考: https://www.taygeta.com/random/gaussian.html // Box-Muller的介绍
https://cosx.org/2015/06/generating-normal-distr-variates // 对比介绍
https://www.zhihu.com/question/29971598
Box-Muller 与 ziggurat的更多相关文章
- <<Numerical Analysis>>笔记
		
2ed, by Timothy Sauer DEFINITION 1.3A solution is correct within p decimal places if the error is l ...
 - Python下探究随机数的产生原理和算法
		
资源下载 #本文PDF版下载 Python下探究随机数的产生原理和算法(或者单击我博客园右上角的github小标,找到lab102的W7目录下即可) #本文代码下载 几种随机数算法集合(和下文出现过的 ...
 - <Numerical Analysis>(by Timothy Sauer)  Notes
		
2ed, by Timothy Sauer DEFINITION 1.3A solution is correct within p decimal places if the error is l ...
 - QuantLib 金融计算——数学工具之随机数发生器
		
目录 QuantLib 金融计算--数学工具之随机数发生器 概述 伪随机数 正态分布(伪)随机数 拟随机数 HaltonRsg SobolRsg 两类随机数的收敛性比较 如果未做特别说明,文中的程序都 ...
 - Virtual Box配置CentOS7网络(图文教程)
		
之前很多次安装CentOS7虚拟机,每次配置网络在网上找教程,今天总结一下,全图文配置,方便以后查看. Virtual Box可选的网络接入方式包括: NAT 网络地址转换模式(NAT,Network ...
 - Linux监控工具介绍系列——OSWatcher Black Box
		
OSWatcher Balck Box简介 OSWatcher Black Box (oswbb)是Oracle开发.提供的一个小巧,但是实用.强大的系统工具,它可以用来抓取操作系统的性能指标,用 ...
 - 使用packer制作vagrant centos box
		
使用packer制作vagrant box:centos 制作vagrant box,网上有教程,可以自己step by step的操作.不过直接使用虚拟在VirtualBox中制作vagrant b ...
 - 快速打造跨平台开发环境 vagrant + virtualbox + box
		
工欲善其事必先利其器,开发环境 和 开发工具 就是 我们开发人员的剑,所以我们需要一个快并且好用的剑 刚开始做开发的时候的都是把开发环境 配置在 自己的电脑上,随着后面我们接触的东西越来越多,慢慢的电 ...
 - CSS3伸缩盒Flexible Box
		
这是一种全新的布局,在移动端非常实用,IE对此布局的相关的兼容不是很好,Firefox.Chrome.Safrai等需要加浏览器前缀. 先说说这种布局的特点: 1)移动端由于屏幕宽度都不一样,在布局的 ...
 
随机推荐
- IDEA常见设置
			
对于eclipse实在忍无可忍,各种功能各种bug..换回IDEA IDEA常见问题(其实不是问题,代码规范而已) 1.解决无限 This file is indented with tabs ins ...
 - 自学Python6.4-内置模块(2)
			
自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...
 - 洛谷 P3237 [HNOI2014]米特运输 解题报告
			
P3237 [HNOI2014]米特运输 题目描述 米特是\(D\)星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储存一直是一个大问题. \(D\)星上有 ...
 - Java_io体系之RandomAccessFile简介、走进源码及示例——20
			
Java_io体系之RandomAccessFile简介.走进源码及示例——20 RandomAccessFile 1. 类功能简介: 文件随机访问流.关心几个特点: 1.他实现的接口不再 ...
 - android sqlite批量插入数据速度解决方案
			
转自 http://hi.baidu.com/hfutonline/blog/item/62b1e4de8bdf4b2e5882dd28.html 最近在做android项目的时候遇到一个问题,应用程 ...
 - Eclipse:构造函数不提示才发现
			
用Eclipse快一年了,今天才发现,原来按下 Alt+? 就可以显示构造函数中的参数. 想一想这一年都不知道是怎么过的,遇到构造函数时,郁闷啊... 2007-11-01
 - 关于jqGrid中GridUnload方法的困惑
			
首先 GridUnload 这个方法在 4.7.1 + 的版本中已经删除,直接把4.7.1中的grid.common.js合来用就行. GridUnload 这个方法是直接删除原来的table,重新生 ...
 - printf()格式化输出详解
			
% - 0 m.n l或h 格式字符 下面对组成格式说明的各项加以说明: ①%:表示格式说明的起始符号,不可缺少. ②-:有-表示左对齐输出,如省略表示右对齐输出. ③0:有0表示指定空位填0,如省略 ...
 - .net MVC使用NPOI读取Excel模板,再写入数据
			
NPOI其实已经介绍的差不多了,再贴一个方便以后复制粘贴. 亮点其实是 Server.MapPath 这个东西,可以找到MVC工程下的文件夹,找路径还是很方便的. /// <summary> ...
 - Unity PC端发布失败解决办法
			
Unity的PC端有时候发布的时候报错.原因可能是你的游戏里面使用了NGUI的label,而且字体选择的是unity自带的字体.因为支持中文.在选择unity自带的字体时最好都选一样的字体.如果一个l ...