蒙特卡罗方法求非概率分布的随机数

问题

假如有四个选项ABCD,每个选项的概率不一样,比如A-0.01 B-0.45 C-0.35 D-0.19 。
如果要从四个选项中任选一个的话,选出的选项尽可能的符合对应的概率。如选100次,才会选出一个A出来。怎么实现?
概率图

算法

请参考 蒙特卡罗方法

思路

从ABCD中,随机选择一个作为候选选项,然后在从0,1中随机产生一个随机数,如果此随机数大于候选选项对应的概率,那么重新选择。若随机数小于等于候选选项的概率,那么此候选选项就是我们要的随机数。

    val array = Array("A", "B", "C", "D")
    val map = Map("A" -> 0.01, "B" -> 0.45, "C" -> 0.35, "D" -> 0.19)
  /**
    * 返回0-$(length-1)的随机整数
    *
    * @param length
    * @return
    */
  private def nextInt(length: Int): Int = {
    (random * length).toInt
  }
  /**
    * 随机从ABCD中选择一个选项,作为X,然后在从0-1中选择一个数值作为Y,那么如果Y大于X对应的概率,递归重头开始选,否则,X就是我们要选择的值。
    *
    * @param array 选项数组
    * @param map   选项对应的概率
    * @return 本次选出的选项
    */
  private def nextValue(array: Array[String], map: Map[String, Double]): String = {
    val x = array(nextInt(array.length))
    val y = random
    if (y > map(x)) {
      //继续nextValue
      nextValue(array, map)
    } else {
      x
    }
  }
  //此处用到了尾递归

测试代码

  def main(args: Array[String]): Unit = {
    //测试长度
    val length = 100000000
    val start = System.currentTimeMillis()
    val allResult = (0 to length).map(x => nextValue(array, map))
    val end = System.currentTimeMillis()
    println(s"计算${length}个随机数,共花费${(end - start) / 1000}秒")

    array.foreach(x => {
      val count = allResult.count(_.equals(x))
      println((s"${x}共随机获得${count}次,概率为${BigDecimal.valueOf(count) / 		BigDecimal.valueOf(length).toDouble}"))
    })
  }

输出结果

计算100000000个随机数,共花费29A共随机获得998503次,概率为0.00998503
B共随机获得44999964次,概率为0.44999964
C共随机获得35003001次,概率为0.35003001
D共随机获得18998533次,概率为0.18998533

posted on   luckuan1985  阅读(387)  评论(0编辑  收藏  举报

编辑推荐:
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
阅读排行:
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· Winform-耗时操作导致界面渲染滞后
· Phi小模型开发教程:C#使用本地模型Phi视觉模型分析图像,实现图片分类、搜索等功能
· 语音处理 开源项目 EchoSharp
· drools 规则引擎和 solon-flow 哪个好?solon-flow 简明教程
< 2025年1月 >
29 30 31 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 1
2 3 4 5 6 7 8

统计

点击右上角即可分享
微信分享提示