可控概率抽奖算法

说明

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

代码

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。
php 复制代码
$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');

验算

php 复制代码
$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期望次
1 999323 1000000 500374 500000 100303 100000 0 0
2 1001144 1000000 498732 500000 100124 100000 0 0
3 999285 1000000 500662 500000 100053 100000 0 0

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

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

技术上:随机范围可控,但是随机值不可控,随机值可控就不叫随机了,有误差正常,本来随机就是个概率问题。

业务上:可通过库存的限制和其它业务逻辑来避免误差带来的问题。

数值上:若硬要实现0误差的精确控制,则需要动态获取权重值,抽中哪条数据,递减那条数据的权重值即可(同时要避免mt_rand();函数参数2小于参数1的情况出现)。

相关推荐
睡觉就不困鸭12 分钟前
第十七天 翻转字符串里的单词
数据结构·算法·哈希算法·散列表
A_aspectJ15 分钟前
【Java基础开发】基于 Java Swing +MySQL + JDBC 版实现图书管理系统
java·开发语言·mysql
TE-茶叶蛋15 分钟前
Spring最核心扩展点:BeanPostProcessor
java·后端·spring
ulias21216 分钟前
leetcode热题 - 4
算法·leetcode·职场和发展
学术阿凡提17 分钟前
Spring Boot 优雅实现异步调用:从入门到自定义线程池与异常处理
java·数据库·算法
MicroTech202527 分钟前
微算法科技(NASDAQ :MLGO)量子化边缘检测技术:重塑图像处理的新范式
图像处理·科技·算法
WolfGang00732132 分钟前
代码随想录算法训练营 Day47 | 图论 part05
算法·图论
猿长大人40 分钟前
算法 | 轮廓提取随笔 —— 关于像素、阈值和直觉的碎碎念
图像处理·算法
阿丰资源42 分钟前
基于SpringBoot智能化体育馆管理系统(附源码+文档+数据库,一键运行)
数据库·spring boot·后端
啦啦啦_99991 小时前
1. 线性回归之 向量&矩阵
算法·矩阵·线性回归