翼度科技»论坛 编程开发 PHP 查看内容

可控概率抽奖算法

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
说明

本文PHP语言去实现,只实现核心可控概率引擎,库存判断等其它业务需要其它代码配合实现。
代码
  1. /**
  2. * @function 封装可控概率的抽奖功能
  3. * @param    $arr        array  数据集合
  4. * @param    $weight_key string 权重字段
  5. * @return   array       被选中的元素
  6. */
  7. function controllableProbability($arr, $weight_key = 'weight') {
  8.     $total_probability = 0;
  9.     foreach($arr as $v) {
  10.         $total_probability = bcadd($total_probability, $v[$weight_key], 2);
  11.     }
  12.     $rand = mt_rand(1, intval($total_probability));
  13.     foreach ($arr as $val) {
  14.         if ($rand <= $val[$weight_key]) {break;}
  15.         $rand -= $val[$weight_key];
  16.         next($arr);
  17.     }
  18.     //想要返回key,使用return key($arr);
  19.     return current($arr);
  20. }
复制代码
验算
  1. $arr = [
  2.     ['id' => 1, 'name' => '谢谢惠顾', 'weight' => 10],
  3.     ['id' => 2, 'name' => '中2元', 'weight' => 5],
  4.     ['id' => 3, 'name' => '中5元', 'weight' => 1],
  5.     ['id' => 4, 'name' => '中50W', 'weight' => 0],
  6. ];
  7. //参数1是数组,参数2是告诉controllableProbability函数哪个字段为改概率字段
  8. controllableProbability($arr, 'weight');
复制代码
3轮抽奖,每轮抽160万次,可得以下表格:
轮次谢谢惠顾实际次数谢谢惠顾期望值中2元实际次数中2元期望值中5元实际次数中5元期望值中50W实际次数中50W期望次1999323100000050037450000010030310000000210011441000000498732500000100124100000003999285100000050066250000010005310000000以谢谢惠顾为例纵向对比:
项目第一轮第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的情况出现)。

来源:https://www.cnblogs.com/phpphp/p/18007246
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具