离散数学模拟微信红包算法升级版

17 篇文章 0 订阅

可以自定义红包总金额,总包数,每包最小金额

<?php
    
    /**
    * 红包类
    */
    class RedPacket
    {
        // 要发的红包总金额
        private $total = 0.01;
        // 总共要发红包总包数
        private $bags = 1;
        // 每包最小红包金额数
        private $min = 0.01;

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

        /**
         * [发红包]
         * @return [array] [红包的每包金额数组]
         */
        public function give_red_packets()
        {
            $redpacket_arr = [];
            //根据最小值不一样,需要转化
            switch (true) {
                case $this->min >= 1:
                    $right_value = 1;
                    break;
                case $this->min >= 0.1:
                    $right_value = 10;
                    break;
                case $this->min >= 0.01:
                    $right_value = 100;
                    break;
            }

            for($i = 1;$i < $this->bags;$i++){//设置循环,边界值是红包数-1
                //保证后面至少有($bags - $i)个最小金额可以发,通过公式模拟数学中的离散模型
                $safe = bcdiv(($this->total - ($this->bags - $i) * $this->min), ($this->bags - $i), 2);
                //根据离散数学模型得到每个红包的金额
                $rand = rand(0, bcmul($safe - $this->min, $right_value, 2)) + $this->min;

                //如果大于倍值,需要转化,反之,不需要。为了防止有的红包金额小于设定的最小金额
                if ($rand >= ($this->min * $right_value)) {
                    $money = bcdiv($rand, $right_value, 2);
                } else {
                    $money = strval($rand);
                }

                $this->total -= $money; //替换$total的值
                $redpacket_arr[] = number_format($money, 2);//把每个红包金额数格式化,存起来
            }
            $left = number_format($this->total, 2);//调用number_format()方法,对数字$total格式化
            $redpacket_arr[] = $left;//输出最后一个红包

            return $redpacket_arr;
        }
    }

    //发红包
    $redpacket = new RedPacket(881.88, 20, 1.5);
    $redpacket_arr = $redpacket->give_red_packets();
    echo '<pre>';
    print_r($redpacket_arr);
    print_r('红包总金额:' . array_sum($redpacket_arr));
    echo '</pre>';

881.88元,20包,每包至少1.5元

效果截图:

100元,33包,每包至少0.01元

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值