一、为什么需要服从正态分布的随机函数

一般我们经常使用的随机数函数 Math.random() 产生的是服从均匀分布的随机数,能够模拟等概率出现的情况,例如 扔一个骰子,1到6点的概率应该相等,但现实生活中更多的随机现象是符合正态分布的,例如20岁成年人的体重分布等。

假如我们在制作一个游戏,要随机设定许许多多 NPC 的身高,如果还用Math.random(),生成从140 到 220 之间的数字,就会发现每个身高段的人数是一样多的,这是比较无趣的,这样的世界也与我们习惯不同,现实应该是特别高和特别矮的都很少,处于中间的人数最多,这就要求随机函数符合正态分布。

二、正态分布复习

图片来自:http://zh.wikipedia.org/zh-cn/%E6%AD%A3%E6%80%81%E5%88%86%E5%B8%83

具体性质也请查阅上面链接,描述正态分布的主要特征是均值和方差,如上图,最左的倒钟形图的均值为-2, 其余为0 ;

方差越大,钟形越扁平,方差越小越陡;

  • 密度函数图像关于均值对称。
  • 在x=μ±σ处,曲线有拐点。
  • 函数曲线下68.26%的面积在平均数左右的一个标准差σ的区间内。
  • 95.44%的面积在平均数左右两个标准差2σ的区间内。
  • 99.74%的面积在平均数左右三个标准差3σ的区间内。

当均值为0, 方差为 1 时称为标准正态分布;

三、由均匀分布经 “Box-Muller法” 转换为正态分布

通过查阅文献可知(请参见:http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform),有一个称为 Box-Muller (1958) 转换的算法能够将两个在区间(0,1] 的均匀分布转化为标准正态分布,其公式为:

y1 = sqrt( - 2 ln(u) ) cos( 2 pi v )

y2 = sqrt( - 2 ln(u) ) sin( 2 pi v )

因为三角函数计算较慢,我们可以通过上述公式的一个 polar form(极坐标形式)能够简化计算,

算法描述如下:

function getNumberInNormalDistribution(mean,std_dev){
return mean+(randomNormalDistribution()*std_dev);
} function randomNormalDistribution(){
var u=0.0, v=0.0, w=0.0, c=0.0;
do{
//获得两个(-1,1)的独立随机变量
u=Math.random()*2-1.0;
v=Math.random()*2-1.0;
w=u*u+v*v;
}while(w==0.0||w>=1.0)
//这里就是 Box-Muller转换
c=Math.sqrt((-2*Math.log(w))/w);
//返回2个标准正态分布的随机数,封装进一个数组返回
//当然,因为这个函数运行较快,也可以扔掉一个
//return [u*c,v*c];
return u*c;
}

因此,假如我们要获得均值为180,要68.26%左右的NPC身高都在[170,190]之内,即1个标准差范围内,因此标准差为10, 可以通过getNumberInNormalDistribution(180,10) 调用,我们实验1000000词,得到结果如下:

// 身高:频率
128:1
132:1
133:1
134:1
135:1
136:2
137:4
138:8
139:11
140:14
141:19
142:28
143:41
144:54
145:80
146:133
147:153
148:235
149:333
150:429
151:598
152:764
153:1059
154:1314
155:1776
156:2290
157:2835
158:3503
159:4373
160:5513
161:6475
162:7809
163:9437
164:11189
165:13282
166:15020
167:17239
168:19215
169:21597
170:24336
171:26684
172:29000
173:31413
174:33179
175:35027
176:37084
177:38047
178:38968
179:39635
180:39700
181:39548
182:38960
183:38674
184:36948
185:35220
186:33224
187:31038
188:29198
189:26668
190:23893
191:21662
192:19476
193:16898
194:15056
195:13046
196:10971
197:9456
198:7928
199:6697
200:5370
201:4334
202:3548
203:2810
204:2330
205:1765
206:1350
207:1093
208:797
209:595
210:371
211:328
212:255
213:165
214:121
215:91
216:71
217:29
218:32
219:28
220:20
221:6
222:7
223:7
224:3
225:2
228:1

绘制成柱状图如下:

可见,这是有着非常明显的正态分布图像特征。

四、由均匀分布叠加获得正态分布

我们需要祭出万能的中心极限定理。

根据独立同分布的中心极限定理:设随机变量X1,X2,...Xn,...相互独立,服从同一分布,且数学期望为μ,标准差为σ (σ>0),则随机变量之和的标准化变量:

Y=((X1+X2+...+Xn)-nμ)/(sqrt(n)*sqrt(σ)) 近似服从标准正态分布 N(0,1)

如果我们将足够多个均匀分布随机变量相加,相加之和将服从正态分布。但是,我们需要累加多少个均匀分布才能较好低近似正态分布呢?

由于 X~U(0, 1) , 可得 μ=1/2, σ=sqrt(1/12),代入上面的式子即可近似模拟随机变量之和的概率密度函数(p.d.f).

下图是由2个服从 U(0,1) 分布的随机变量相加得到的 p.d.f 图像:

如果我们增加累加的均匀分布的数量会怎样呢?

上图是 n=3 时的图像,可以看到正态分布的形状出来了,但顶端还略为平缓。

特别低,当n=12时 (随机变量(X1+X2+...+Xn)的均值为6,方差为1)  这时有一个很好的特点,公式 Y=((X1+X2+...+Xn)-nμ)/(sqrt(n)*sqrt(σ)) 的分母正好为1,因此简化成了 Y=((X1+X2+...+Xn)-nμ),非常便于编程计算,并且已经非常接近于标准正态分布,请见下图:

也就是说均值为μ,标准差为σ 的独立同分布变量 X1,X2, ..., Xn 的算数平均数  T=(X1+X2+ ...+ Xn)/n,当n充分大时,近似地服从均值为μ,方差为σ*σ/n 的正态分布。

最后,代码如下:

function getNumberInNormalDistribution(mean,std_dev){
return mean+(uniform2NormalDistribution()*std_dev);
} function uniform2NormalDistribution(){
var sum=0.0;
for(var i=0; i<12; i++){
sum=sum+Math.random();
}
return sum-6.0;
}

同样,将产生100万个随机数按频率画出直方图如下:

如何产生服从均匀分布的随机数呢?

请见上篇:

Javascript 随机数函数 学习之一:产生服从均匀分布随机数

最新文章

  1. RecyclerView
  2. webform 复合控件
  3. MMC不能打开文件D:\Program Files\Microsoft SQL Server\80\Tools\BINN\SQL Server Enterprise Manager.MSC
  4. CentOS FTP基于虚拟用户的配置
  5. JavaWeb学习----JSP脚本元素、指令元素、动作元素
  6. ASP.NET MVC4中调用WEB API的四个方法
  7. struts2文件上传类型的过滤
  8. Python datetime time 常用操作
  9. jQuery Mobile基础
  10. Sublime Text 2快捷键大全
  11. dubbo的简单实现
  12. Lintcode248 Count of Smaller Number solution 题解
  13. maven入门(7)maven项目(组件)的坐标
  14. Mybatis源码分析之缓存
  15. excel写入操作
  16. 运行Keras版本的Faster R-CNN(1)
  17. python第三十天-类
  18. [No0000BC]ADO.NET中的几个主要对象
  19. metasploit framework(十二):sql server扫描
  20. Task 6.2冲刺会议六 /2015-5-19

热门文章

  1. SpringBoot入门之内嵌Tomcat配置
  2. 在vue里面使用iVew框架
  3. 判断一个类是否为另一个类的实例 instanceof关键字和isAssignableFrom方法的区别
  4. element UI form 验证
  5. Solr6.5配置中文分词IKAnalyzer和拼音分词pinyinAnalyzer (二)
  6. spring 后处理器
  7. hexo 静态页面生成后页面打不开的问题
  8. 【转】谷歌三大核心技术(二)Google MapReduce中文版
  9. pyenv docter检测出configure: error: OpenSSL is not installed.解决方案
  10. Spring Boot + Spring Cloud 实现权限管理系统 后端篇(七):集成 Druid 数据源