抢红包算法

<?php
/* * 生成红包的函数 */

function getRandMoney($totalMoney, $totalPeople = 2, $miniMoney = 1)
{
    $randRemainMoney = $totalMoney - $totalPeople * $miniMoney; //剩余需要随机的钱数
    return _getRandMoney($randRemainMoney, $totalPeople, $miniMoney);
}

/* * 红包生成的逻辑代码 */

function _getRandMoney($totalMoney, $totalPeople, $miniMoney)
{
    $returnMessage = array('status' => 1, 'data' => NULL);
    if ($totalMoney > 0) {
        $returnMessage['data'] = _randMoney($totalMoney, $totalPeople, $miniMoney);
    } elseif ($totalMoney == 0) {
        $returnMessage['data'] = array_fill(0, $totalPeople, 1);
    } else {
        $returnMessage['status'] = -1;
        $returnMessage['data'] = '参数传递有误,生成红包失败';
    }
    return $returnMessage;
}

/* 参数无误,开始生成对应的红包金额 */

function _randMoney($totalMoney, $totalPeople, $miniMoney)
{
    $data = array_fill(0, $totalPeople, $miniMoney);
    if ($totalPeople > 1) {
        foreach ($data as $k => $v) {
            if ($k == $totalPeople - 1) {
                $data[$k] = $totalMoney + $v;
                break;
            } else {
                if ($totalMoney == 0)
                    break;
                $randMoney = rand(0, $totalMoney);
                $totalMoney -= $randMoney;
                $data[$k] = $randMoney + $v;
            }
        }
    }
    return $data;
}

class redpack
{

//总金额
    private $total = 0;
//红包数量
    private $num = 0;
//最小红包金额
    private $min = 0.01;

    public function __construct($total, $num, $min)
    {
        $this->total = $total;
        $this->num = $num;
        $this->min = $min;
    }

//红包结果
    public function getPack()
    {
        $total = $this->total;
        $num = $this->num;
        $min = $this->min;
        for ($i = 1; $i < $num; $i++) {
            $safe_total = ($total - ($num - $i) * $min) / ($num - $i); //随机安全上限
            $money = mt_rand($min * 100, $safe_total * 100) / 100;
            $total = $total - $money;
//红包数据
            $readPack[] = [
                'money' => $money,
                'balance' => $total,
            ];
        }
//最后一个红包,不用随机
        $readPack[] = [
            'money' => $money,
            'balance' => 0,
        ];
//返回结果
        return $readPack;
    }

}

$money = getRandMoney(20, 10, 0.01);
var_dump($money);
$total = 20; //红包总金额
$num = 10; // 分成10个红包,支持10人随机领取
$min = 0.01; //每个人最少能收到0.01元
$redpack = new redpack($total, $num, $min);
$jieguo = $redpack->getPack();
foreach ($jieguo as $key => $val) {
    $n = $key + 1;
    echo '第' . $n . '个红包:' . $val['money'] . ' 元,余额:' . $val['balance'] . ' 元<br>';
}

输出结果:

array (size=2)
  'status' => int 1
  'data' => 
    array (size=10)
      0 => float 5.01
      1 => float 6.01
      2 => float 1.01
      3 => float 5.01
      4 => float 1.01
      5 => float 1.01
      6 => float 0.01
      7 => float 0.01
      8 => float 0.01
      9 => float 0.911个红包:0.6 元,余额:19.4 元
第2个红包:1.23 元,余额:18.17 元
第3个红包:0.47 元,余额:17.7 元
第4个红包:1.12 元,余额:16.58 元
第5个红包:0.37 元,余额:16.21 元
第6个红包:3.4 元,余额:12.81 元
第7个红包:4.02 元,余额:8.79 元
第8个红包:3.85 元,余额:4.94 元
第9个红包:0.96 元,余额:3.98 元
第10个红包:0.96 元,余额:0

不足点:实际情况中还需要考虑并发的情况,使用队列或者加锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值