当前位置: 首页 > article >正文

可控概率抽奖算法

说明

本文PHP语言去实现,只实现核心可控概率引擎,库存判断等其它业务需要其它代码配合实现。

代码

/**
 * @function 封装可控概率的抽奖功能
 * @param    $arr        array  数据集合
 * @param    $weight_key string 权重字段
 * @return   array       被选中的元素
 */
function controllableProbability($arr, $weight_key = 'weight') {
    $total_probability = 0;
    foreach($arr as $v) {
        $total_probability = bcadd($total_probability, $v[$weight_key], 2);
    }
    $rand = mt_rand(1, intval($total_probability));
    foreach ($arr as $val) {
        if ($rand <= $val[$weight_key]) {break;}
        $rand -= $val[$weight_key];
        next($arr);
    }
    //想要返回key,使用return key($arr);
    return current($arr);
}

调用

  1. weight权重概率字段,不是概率字段,不需要总和为100
  2. 如下,代表16个人抽奖,有10人是谢谢惠顾,有5人中2元,有1人中5元,有0人中50W。
$arr = [
    ['id' => 1, 'name' => '谢谢惠顾', 'weight' => 10],
    ['id' => 2, 'name' => '中2元', 'weight' => 5],
    ['id' => 3, 'name' => '中5元', 'weight' => 1],
    ['id' => 4, 'name' => '中50W', 'weight' => 0],
];
//参数1是数组,参数2是告诉controllableProbability函数哪个字段为改概率字段
controllableProbability($arr, 'weight');

验算

$a = 0; $b = 0; $c = 0; $d = 0;
for($i = 0; $i < 1600000; $i++) {
    $res = controllableProbability($arr, 'weight');
    if($res['id'] == 1) $a ++;
    if($res['id'] == 2) $b ++;
    if($res['id'] == 3) $c ++;
    if($res['id'] == 4) $d ++;
}
echo "$a $b $c $d";

3轮抽奖,每轮抽160万次,可得以下表格:

轮次谢谢惠顾实际次数谢谢惠顾期望值中2元实际次数中2元期望值中5元实际次数中5元期望值中50W实际次数中50W期望次
1999323100000050037450000010030310000000
21001144100000049873250000010012410000000
3999285100000050066250000010005310000000

以谢谢惠顾为例纵向对比:

项目第一轮第2轮第3轮
谢谢惠顾实际次数9993231001144999285
谢谢惠顾期望次数100000100000100000
谢谢惠顾实际概率62.46%62.57%62.46%
谢谢惠顾期望概率62.50%62.50%62.50%
误差率-0.04%+0.07%-0.04%

技术上:随机范围可控,但是随机值不可控,随机值可控就不叫随机了,有误差正常,本来随机就是个概率问题。
业务上:可通过库存的限制和其它业务逻辑来避免误差带来的问题。
数值上:若硬要实现0误差的精确控制,则需要动态获取权重值,抽中哪条数据,递减那条数据的权重值即可(同时要避免mt_rand();函数参数2小于参数1的情况出现)。


http://www.kler.cn/a/228628.html

相关文章:

  • Jenkins 启动
  • Spring Boot 3.3.4 升级导致 Logback 之前回滚策略配置不兼容问题解决
  • jlatexmath-android如何实现自定义渲染字符
  • 强推未发表!3D图!Transformer-LSTM+NSGAII工艺参数优化、工程设计优化!
  • C# 解析 HTML 实战指南
  • 解决 多层跳板机情况下,ssh可以成功连但是VSCode失败
  • mac下载工具:JDownloader 2 for Mac 中文版
  • Backtrader 文档学习-Indicators- TA-Lib
  • openGauss学习笔记-214 openGauss 性能调优-确定性能调优范围
  • 多输入多输出 | Matlab实现PSO-LSTM粒子群优化长短期记忆神经网络多输入多输出预测
  • BUU UPLOAD COURSE 1
  • PHP框架详解 - symfony框架
  • 备战蓝桥杯---数据结构与STL应用(进阶2)
  • 【Redis】实现缓存及相关问题
  • 网络安全-端口扫描和服务识别的几种方式
  • WPF DataTemplate内重写BorderBrush,VisualBrush内数据源绑定提示绑定失败
  • 数据挖掘实战-基于决策树算法构建北京市空气质量预测模型
  • 前端excel带样式导出 exceljs 插件的使用
  • C语言动态库全面深入剖析
  • [office] 在Excel2010中设定某些单元格数据不参与排序的方法介绍 #其他#知识分享#笔记
  • golang 创建unix socket http服务端
  • 如何使用linux inotifywait inotifywatch对文件增删修改进行监测和实现数据同步
  • 最短编辑距离问题与动态规划----LeetCode 72.编辑距离
  • Linux底层基础知识
  • 回归预测 | Matlab实现WOA-CNN-LSTM-Attention鲸鱼算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制)
  • Go语言学习踩坑记