引子
一把武器的品质有分为最下级、下级、中级、上级、最上级五档,我希望在击杀一只怪物的时候,这把武器的掉率:最下级>下级>中级>上级>最上级,问如何设计满足上面的需求?
在游戏设计的过程中,经常会碰到需要设计很多不同的概率分布来达到一个系统的设计目的,让玩家在体验这个系统的时候感受更好,所以这时候均匀分布随机就不够用了,就需要开始为游戏设计不同的概率分布随机数。这里,介绍两种方法用来生成任意概率分布的随机数:逆变换方法、舍取方法。这两种算法其原理已被证实,所以这里不再进行论证,如果需要去探究其原理,可以去中国知网上搜索相关论文进行查看。
逆变换方法(Inverse Transform Method,ITM)
最简单的生成算法是Inverse Transform Method(下文简称ITM)。如果我们可以给出概率分布的累积分布函数(下文简称CDF)及其逆函数的解析表达式,则可以非常简单便捷的生成指定分布随机数。

  • ITM算法思路

  1. 根据给出的概率密度函数f(X)(PDF)积分得到其累积分布函数F(X)(CDF)
  2. 生成一个服从均匀分布的随机数S~U(0,1)
  3. 根据累积分布函数Y=F(X),求得其反函数X=F-1(Y)
  4. 返回X=F-1(S)作为本次生成的随机数

这种算法在实现时必须保证给出的概率密度函数,能够求出其累积分布函数CDF的逆函数,否则将无法求得所需要的随机数。下面就以指数分布为例,实现生成符合指数分布的随机数。

  • ITM方法的VBA实现

这里,先给出指数分布的PDF和CDF,λ是分布的一个参数,常被称为率参数(rate parameter)且λ>0。
概率密度函数

累积分布函数

 1 Option Explicit
 2 Option Base 1
 3
 4 Sub expDistribution()
 5 Range("J:J").ClearContents
 6 Range("J1") = "指数分布随机数"
 7
 8 Dim src As Single 'src:用来生成均匀分布随机数U(0,1)
 9 Dim λ As Single 'λ:指数分布的参数
10 Dim num As Integer 'num:生成的随机数个数
11 Dim arr() As Integer 'arr():用来保存生成的随机数结果
12
13 λ = Range("C10").value
14 num = Range("C11").value
15
16 ReDim arr(1 To num) As Integer
17 Dim i As Integer
18 For i = 1 To num Step 1
19 src = Rnd()
20 arr(i) = WorksheetFunction.RoundDown(-1 / λ * Log(src), 0)
21 Next
22
23 For i = 1 To num Step 1
24 Range("J" & i + 1) = arr(i)
25 Next
26 End Sub

View Code

  • ITM实现结果

上述代码中可以看到,我将自己设定的30000个随机数(参数λ=0.3)都打印在表中J列单元格,这里给出最后的统计数据,如下。

可以看到,最终生成的30000个随机数,其数值的个数分布是符合之前给定的指数分布的。这种算法较为简洁高效,在能够使用的情况下,可以考虑优先使用该算法。
舍取方法(Acceptance-Rejection Method,ARM)
当无法给出CDF逆函数的解析表达式时,Acceptance-Rejection Method(下文简称ARM)是另外的选择。ARM的适用范围比ITM要大,只要给出概率密度函数(下文简称PDF)的解析表达式即可,而大多数常用分布的PDF是可以查到的。

  • ARM算法思路

    1. 设定我们需要实现的概率密度分布函数PDF为f(x),确定f(x)的定义域[xmin,xmax]、值域[ymin,ymax]
    2. 生成一个均匀分布随机数X~U(xmin,xmax)
    3. 生成一个均匀分布随机数Y~U(ymin,ymax)
    4. 如果Y≤f(X),则返回X作为本次的随机数;否则回到第2步

下面,依旧以指数分布为例,利用ARM实现该分布的随机数生成。

  • ARM方法的VBA实现

 1 Option Explicit
 2 Option Base 1
 3
 4
 5
 6 Sub ARMexpDistribution()
 7 Range("J:J").ClearContents
 8 Range("J1") = "指数分布随机数"
 9
10 Dim src As Single 'src:用来生成第一个均匀分布随机数src~U(0,1 / λ * Log(λ / 0.0001))
11 Dim dst As Single 'dst:用来生成第二个均匀分布随机数dst~U(0,λ)
12 Dim λ As Single 'λ:指数分布的参数
13 Dim num As Integer 'num:生成的随机数个数
14 Dim arr() As Integer 'arr():用来保存生成的随机数结果
15
16 λ = Range("C11").value
17 num = Range("C12").value
18
19 ReDim arr(1 To num) As Integer
20 Dim i As Integer
21 For i = 1 To num Step 1
22 Do
23 src = Rnd() * 1 / λ * Log(λ / 0.0001)
24 dst = Rnd() * λ
25 Loop While dst > λ * Exp(-λ * src)
26 arr(i) = WorksheetFunction.RoundDown(src, 0)
27 Next
28
29 For i = 1 To num Step 1
30 Range("J" & i + 1) = arr(i)
31 Next
32 End Sub

View Code

  • ARM实现结果

同样是生成30000个随机数,同样是参数λ=0.3,可以看到下面的列表中的统计数据以及统计图和第一种方法的实现结果是想吻合的,验证了这个方法的可行性。ARM本质上是一种模拟方法,而非直接数学方法。它每次生成新的随机数后,通过另一个随机数来保证其被接受概率服从指定的PDF。显然ARM从效率上不如ITM,但是其适应性更广,在无法得到CDF的逆函数时,ARM是不错的选择。

如果一种概率分布是由很多常见的概率分布组合而成,那么可以先生成常见概率分布的随机数,然后进行组合得到最终的概率分布随机数。

转载于:https://www.cnblogs.com/architecture101-gbt/p/8303378.html

VBA实现两种方法生成任意概率分布的随机数相关推荐

  1. xlwings库 ==> Python调用VBA 的两种方法

    之前被问到,Python 很强大,但是需要单独安装,而VBA是office自带的, 那么两者结合的话,如何用Python调用VBA呢? 代码如下(其中 A 是测试文件 宏的名字): VBA代码: Su ...

  2. php强中弱密码,PHP两种方法生成强密码

    原文:http://www.nowamagic.net/librarys/veda/detail/1210 效果演示 第一种生成方式: o6rkNmI0f 第二种生成方式: 745IFsXt? PHP ...

  3. python读取视频流提取视频帧的两种方法_ffmpeg-python 任意提取视频帧

    ▶ 环境准备 1.安装 FFmpeg 2.安装 ffmpeg-python pip3 install ffmpeg-python 3.[可选]安装 opencv-python pip3 install ...

  4. 条码生成器中生成药品电子监管码的两种方法

    在生成药品电子监管码之前,我们首先要对药品电子监管码有一个简单的了解.药品电子监管码共计20位数字,前7位是产品资源码(包含企业信息,药品名称,批准文号等等信息),8到16位是单件产品的序列号,最后4 ...

  5. elf格式转换为hex格式文件的两种方法

    这周工作终于不太忙了,可以写点笔记总结一下了. 之前的文章如何在Keil-MDK开发环境生成Bin格式文件,介绍了如何在Keil开发环境使用fromelf软件,将生成的axf文件转换为bin文件,这次 ...

  6. elf格式转换为hex格式文件的两种方法 1

    这周工作终于不太忙了,可以写点笔记总结一下了. 之前的文章如何在Keil-MDK开发环境生成Bin格式文件,介绍了如何在Keil开发环境使用fromelf软件,将生成的axf文件转换为bin文件,这次 ...

  7. php 自动生成查询密码,php自动生成新密码的两种方法

    php自动生成新密码的两种方法,方法一采用的是随机种子,方法是乱序数组,异曲同工吧. 有需要的朋友可以参考下. 方法1: 代码示例: /* * php自动生成新密码自定义函数 适用环境: PHP5.2 ...

  8. python requirements.txt_python生成requirements.txt的两种方法

    这篇文章主要介绍了python生成requirements.txt的两种方法,每种方法给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 python项目如何在另一个环境上重新构建项目 ...

  9. python生成100个随机数_Python_0——100闭区间产生3个随机数,两种方法排序

    ''' 题目:0--100闭区间产生3个随机数,两种方法排序 法1:暴力遍历 法2:max(a,b,c)min(a,b,c) 注意:random,radint(0--100)产生随机数 '''impo ...

最新文章

  1. PESCMS Ticket 客服工单系统 v1.2.5 发布
  2. 面试:URI中的 “//” 有什么用?
  3. Java 源码中 unchecked 什么意思
  4. SQL 触发器的使用
  5. lamda过滤_java 使用Lambda和filter对对象集合过滤
  6. LeetCode 1090. 受标签影响的最大值(优先队列)
  7. HTML常用标签+CSS基础
  8. 关于Git和Github
  9. 从HDFS的写入和读取中,我发现了点东西
  10. java app支付_Java 微信支付之APP支付服务端 (一)
  11. PHP批量去除PHP文件中bom的代码
  12. 修改maven默认仓库(即repository)的路径
  13. DPDK之PMD原理
  14. python文本风格_Python的代码风格
  15. 熊猫烧香delphi编写免费源代码
  16. x86_64 x86 amd64 i386 i686 aarch64等词语含义
  17. python函数长度单位换算,(最新整理)长度单位换算
  18. 教会如何使用WordPress提供在线讲道
  19. 个人博客网站建设详细版
  20. day 18 类与类之间的关系

热门文章

  1. 面试谈薪,被 HR 压价,怎么办?
  2. 10个 Python 程序员,9个不合格?
  3. qq邮箱高频率邮件来源自动屏蔽的信任办法
  4. 现在企业会要求JAVA人员会怎样的技术呢?
  5. Oracle:PL/SQL 中如何使用Array
  6. MAC安装Win10出现”在efi系统上,windows只能安装到gpt分区”问题的解决
  7. Java SE 9(JDK9)环境安装及交互式编程环境Jshell使用示例
  8. [AlwaysOn Availability Groups]排查:Primary上的修改无法在Secondary体现
  9. Repeater 嵌套
  10. fiddler 在火狐(firefox)下无效的问题 ——Fiddler监听Firefox、Chrome中的http请求