首页 文章 红包算法

红包算法

来源:https://segmentfault.com/a/1190000010210451 发布时间:2021-01-15 16:47:25 作者:Soul-Yang 阅读量:841

产品经理 : 老司机,你那边开发个领取红包的版块。我给一定的金额总数,红包个数,最高发放金额,以及最低发放金额,你要随机生成固定个数的红包,红包总额不能超过金额总数。
老司机 : 你(笔者),去实现这个算法,把生成的红包全部丢到数据库(redis集合)里面。

好吧,就这样,这个需求就让我实现了。其实业务看起来说的很复杂,其实就是例如我有1000元,我想发放100个红包,最高不能超过20块,最低不能低于1块。
当时我也不太清楚这个算法要怎么写,上网搜索了下,找到一种比较合理的算法,是用微积分去实现(我会把代码贴出来)的。算法原理如下



(原文地址:http://blog.csdn.net/cleverco...
我刚开始觉得这个算法确实很不错,但仔细看了下里面的源码后觉得会比较耗性能,而且回头一看公司的需求,其实也就个红包生成(在项目经理没要求需要正态分布的情况下),没必要把复杂简单的东西弄复杂了。所以我思来想去想了一个晚上,终于写出了个比较合理的算法。

/*
 * 获取随机红包
 * min<k<max
 * min(n-1) <= money - k <= (n-1)max
 * k <= money-(n-1)min
 * k >= money-(n-1)max
 */
function getRedPackage($money, $num, $min, $max)
{
    $data = array();
    if ($min * $num > $money) {
        return array();
    }
    if($max*$num < $money){
        return array();
    }
    while ($num >= 1) {
        $num--;
        $kmix = max($min, $money - $num * $max);
        $kmax = min($max, $money - $num * $min);
        $kAvg = $money / ($num + 1);
        //获取最大值和最小值的距离之间的最小值
        $kDis = min($kAvg - $kmix, $kmax - $kAvg);
        //获取0到1之间的随机数与距离最小值相乘得出浮动区间,这使得浮动区间不会超出范围
        $r = ((float)(rand(1, 10000) / 10000) - 0.5) * $kDis * 2;
        $k = round($kAvg + $r,2);
        $money -= $k;
        $data[] = $k;
    }
    return $data;
}

这个算法的原理其实就是根据剩余不断变化的平均值去加减随机数做到不超过总额,但红包的分布就没那么平均。

  
留言
https://blog.key9.cn/
用户登录
您还没有写任何评论内容!
您已经评论过了!
只能赞一次哦!
您已经收藏啦!