zoukankan      html  css  js  c++  java
  • 红包复杂算法

    <?php
    /*
     * 红包算法
     * */
    class Redpaper
    {
        public $rewardMoney;        #红包金额、单位元
        public $rewardNum;          #红包数量
    
        #执行红包生成算法
        public function splitReward($rewardMoney, $rewardNum, $max, $min)
        {
            #传入红包金额和数量,因为小数在计算过程中会出现很大误差,所以我们直接把金额放大100倍,后面的计算全部用整数进行
            $min = $min * 100;
            $max = $max * 100;
            #预留出一部分钱作为误差补偿,保证每个红包至少有一个最小值
            $this->rewardMoney = $rewardMoney * 100 - $rewardNum * $min;
            $this->rewardNum = $rewardNum;
            #计算出发出红包的平均概率值、精确到小数4位。
            $avgRand = 1 / $this->rewardNum;
            $randArr = array();
            #定义生成的数据总合sum
            $sum = 0;
            $t_count = 0;
            while ($t_count < $rewardNum) {
                #随机产出四个区间的额度
                $c = rand(1, 100);
                if ($c < 15) {
                    $t = round(sqrt(mt_rand(1, 1500)));
                } else if ($c < 65) {
                    $t = round(sqrt(mt_rand(1500, 6500)));
                } else if ($c < 95) {
                    $t = round(sqrt(mt_rand(6500, 9500)));
                } else {
                    $t = round(sqrt(mt_rand(9500, 10000)));
                }
                ++$t_count;
                $sum += $t;
                $randArr[] = $t;
            }
    
            #计算当前生成的随机数的平均值,保留4位小数
            $randAll = round($sum / $rewardNum, 4);
    
            #为将生成的随机数的平均值变成我们要的1/N,计算一下每个随机数要除以的总基数mixrand。此处可以约等处理,产生的误差后边会找齐
            #总基数 = 均值/平均概率
            $mixrand = round($randAll / $avgRand, 4);
    
            #对每一个随机数进行处理,并乘以总金额数来得出这个红包的金额。
            $rewardArr = array();
            foreach ($randArr as $key => $randVal) {
                #单个红包所占比例randVal
                $randVal = round($randVal / $mixrand, 4);
                #算出单个红包金额
                $single = floor($this->rewardMoney * $randVal);
                #小于最小值直接给最小值
                if ($single < $min) {
                    $single += $min;
                }
                #大于最大值直接给最大值
                if ($single > $max) {
                    $single = $max;
                }
                #将红包放入结果数组
                $rewardArr[] = $single;
            }
    
            #对比红包总数的差异、将差值放在第一个红包上
            $rewardAll = array_sum($rewardArr);
            $rewardArr[0] = $rewardMoney * 100 - ($rewardAll - $rewardArr[0]);#此处应使用真正的总金额rewardMoney,$rewardArr[0]可能小于0
    
            #第一个红包小于0时,做修正
            if ($rewardArr[0] < 0) {
                rsort($rewardArr);
                $this->add($rewardArr, $min);
            }
    
            rsort($rewardArr);
            #随机生成的最大值大于指定最大值
            if ($rewardArr[0] > $max) {
                #差额
                $diff = 0;
                foreach ($rewardArr as $k => &$v) {
                    if ($v > $max) {
                        $diff += $v - $max;
                        $v = $max;
                    } else {
                        break;
                    }
                }
                $transfer = round($diff / ($this->rewardNum - $k + 1));
                $this->diff($diff, $rewardArr, $max, $min, $transfer, $k);
            }
            return $rewardArr;
        }
    
        #处理所有超过最大值的红包
        public function diff($diff, &$rewardArr, $max, $min, $transfer, $k)
        {
            #将多余的钱均摊给小于最大值的红包
            for ($i = $k; $i < $this->rewardNum; $i++) {
                #造随机值
                if ($transfer > $min * 20) {
                    $aa = rand($min, $min * 20);
                    if ($i % 2) {
                        $transfer += $aa;
                    } else {
                        $transfer -= $aa;
                    }
                }
                if ($rewardArr[$i] + $transfer > $max) continue;
                if ($diff - $transfer < 0) {
                    $rewardArr[$i] += $diff;
                    $diff = 0;
                    break;
                }
                $rewardArr[$i] += $transfer;
                $diff -= $transfer;
            }
            if ($diff > 0) {
                $i++;
                $this->diff($diff, $rewardArr, $max, $min, $transfer, $k);
            }
        }
    
        #第一个红包小于0,从大红包上往下减
        public function add(&$rewardArr, $min)
        {
            foreach ($rewardArr as &$re) {
                $dev = floor($re / $min);
                if ($dev > 2) {
                    $transfer = $min * floor($dev / 2);
                    $re -= $transfer;
                    $rewardArr[$this->rewardNum - 1] += $transfer;
                } elseif ($dev == 2) {
                    $re -= $min;
                    $rewardArr[$this->rewardNum - 1] += $min;
                } else {
                    break;
                }
            }
            if ($rewardArr[$this->rewardNum - 1] > $min || $rewardArr[$this->rewardNum - 1] == $min) {
                return;
            } else {
                $this->add($rewardArr, $min);
            }
        }
     public    function random_red($total, $num, $max, $min)
        {
            #总共要发的红包金额,留出一个最大值;
            $total = $total - $max;
            $result_merge = $this->splitReward($total, $num, $max - 0.01, $min);
            sort($result_merge);
            $result_merge[1] = $result_merge[1] + $result_merge[0];
            $result_merge[0] = $max * 100;
            foreach ($result_merge as &$v) {
                $v = floor($v) / 100;
            }
            return $result_merge;
        }
    }
    <?php
    header('content-type:text/html;charset=utf-8');
    function dump($arr){
    echo '<pre>'.print_r($arr,TRUE).'</pre>';
    }
    require_once('Redpaper.class.php');
    $total = 10;//红包总金额
    $num = 50;//分发个数
    $max = 1;//最大金额
    $min = 0.01;//最小金额
    $a = new Redpaper();
    $arr = $a->random_red($total, $num, $max, $min);
    dump($arr);

  • 相关阅读:
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
  • 原文地址:https://www.cnblogs.com/kevin-yang123/p/14060481.html
Copyright © 2011-2022 走看看