精华内容
下载资源
问答
  • 随机红包算法

    2021-01-05 15:00:36
    随机红包算法,每个人都有自己的实现思路。 package com.jmmq.load.jim.algorithm; import java.math.BigDecimal; import java.util.Arrays; import java.util.List; import java.util.Random; /** * 红包算法 *...

    随机红包算法,每个人都有自己的实现思路。

    package com.jmmq.load.jim.algorithm;
    
    import java.math.BigDecimal;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Random;
    
    /**
     * 红包算法
     */
    public class RedPacketPrc {
    
        private static final BigDecimal MIN = new BigDecimal("0.01");
    
        public static void main(String[] args) {
    
            String[] rs = redPacketRandom(new BigDecimal(1), 100, false);
            BigDecimal sum = BigDecimal.ZERO;
            for(String str: rs){
                System.out.println(str);
                sum = sum.add(new BigDecimal(str));
            }
            System.out.println("sum:" + sum);
    
            System.out.println("(¯`•._.• •._.•´¯)(¯`•¸•´¯) (¯`•._.• •._.•´¯)(¯`•¸•´¯) (¯`•._.• •._.•´¯)(¯`•¸•´¯)");
    
            String[] res = redPacketOpen(new BigDecimal(20), 6, false);
            BigDecimal sum2 = BigDecimal.ZERO;
            for(String str: res){
                System.out.println(str);
                sum2 = sum2.add(new BigDecimal(str));
            }
            System.out.println("sum2:" + sum2);
        }
    
        /**
         *
         * @param faceValue 面值 单位:元
         * @param amount    人数
         * @param avgFlag 是否平均
         * @return
         *   平均分就不写了
         *   思路一:
         *        按百分比进行随机计算,最后一个进行匝差计算
         */
        public static String[] redPacketRandom(BigDecimal faceValue, int amount, boolean avgFlag){
    
            // 先计算平均数  四舍五入
            BigDecimal perValue = faceValue.divide(new BigDecimal(amount),3, BigDecimal.ROUND_HALF_UP);
    
            // 平均下来最小的红包必须大于等于 1分钱
            if(perValue.compareTo(MIN) == -1){
                throw new RuntimeException("red packet amount OutOfBounds  min = 0.01");
            }
    
            String[] rs = new String[amount];
    
            // 平均
            if(avgFlag){
                // 这里四舍五入重新计算
                perValue = faceValue.divide(new BigDecimal(amount),2, BigDecimal.ROUND_HALF_UP);
                Arrays.fill(rs, perValue.toString());
                // 无法除尽
                if(perValue.multiply(new BigDecimal(amount)).compareTo(faceValue) != 0 ){
                    // 随机获取一个下标
                    int index = new Random().nextInt(amount);
                    rs[index] = String.valueOf(new BigDecimal(rs[index]).add(
                               faceValue.subtract(perValue.multiply(new BigDecimal(amount)))));
    
                }
                return rs;
            }
    
            BigDecimal weightSum = BigDecimal.ZERO;
            BigDecimal redSum = BigDecimal.ZERO;
            BigDecimal[] weights = new BigDecimal[amount];
            // 随机
            for (int i=0; i<rs.length; i++){
                BigDecimal seed = new BigDecimal(new Random().nextInt(amount));
                weightSum = weightSum.add(seed);
                weights[i] = seed;
    
                // 循环最后一个后计算金额
                if(i == rs.length -1){
                    for(int j=0; j<rs.length; j++){
                       // 修改为向下取值,这样差额永远都是正数就不存在吃不掉差额的问题了
                       BigDecimal val = faceValue.multiply(weights[j].divide(weightSum,2, BigDecimal.ROUND_HALF_UP));
                       if(val.compareTo(MIN) == -1){
                           val = MIN;
                       }
                        redSum = redSum.add(val);
                       rs[j] = val.toString();
                    }
                }
            }
    
            BigDecimal diff = faceValue.subtract(redSum);
            if(faceValue.compareTo(redSum) != 0){
    
                // 找到第一个加上或减少diff大于MIN的元素修改金额
                for(int i=0; i<rs.length; i++){
                    if(new BigDecimal(rs[i]).add(diff).compareTo(MIN) > -1 ){
                        rs[i] = new BigDecimal(rs[i]).add(diff).toString();
                        break;
                    }
                }
            }
    
            // 若没有任何一个元素能吃掉差额,因此差额需要进行分摊了,
            // 这里简单粗暴的将循环到大于MIN的都改为MIN同时减少差额
            // 这里代码不进行优化,会写另外一个优化的算法
            if(faceValue.compareTo(redSum) != 0){
                for(int i=0; i<rs.length; i++){
                    if(new BigDecimal(rs[i]).compareTo(MIN) > 0){
                        if(new BigDecimal(rs[i]).add(diff).compareTo(MIN) > -1){
                            rs[i] = new BigDecimal(rs[i]).add(diff).toString();
                            break;
                        } else {
                            diff.add(new BigDecimal(rs[i])).subtract(MIN);
                            rs[i] = MIN.toString();
                        }
                    }
                }
            }
            return rs;
        }
    
    
        /**
         *  上面算法进行优化
         * @param faceValue 面值 单位:元
         * @param amount    人数
         * @param avgFlag 是否平均
         * @return
         *   优化思路:
         *       上面算法为了保证红包最小金额处理上花费了大量的循环来处理
         *       优化上就直接先分配最小金额,然后在进行随机分摊剩余的钱
         */
        public static String[] redPacketOpen(BigDecimal faceValue, int amount, boolean avgFlag){
    
            // 先计算平均数  四舍五入
            BigDecimal perValue = faceValue.divide(new BigDecimal(amount),3, BigDecimal.ROUND_HALF_UP);
    
            // 平均下来最小的红包必须大于等于 1分钱
            if(perValue.compareTo(MIN) == -1){
                throw new RuntimeException("red packet amount OutOfBounds  min = 0.01");
            }
    
            String[] rs = new String[amount];
    
            // 平均
            if(avgFlag){
                // 这里四舍五入重新计算
                perValue = faceValue.divide(new BigDecimal(amount),2, BigDecimal.ROUND_HALF_UP);
                Arrays.fill(rs, perValue.toString());
                // 无法除尽
                if(perValue.multiply(new BigDecimal(amount)).compareTo(faceValue) != 0 ){
                    // 随机获取一个下标
                    int index = new Random().nextInt(amount);
                    rs[index] = String.valueOf(new BigDecimal(rs[index]).add(
                            faceValue.subtract(perValue.multiply(new BigDecimal(amount)))));
    
                }
                return rs;
            }
    
            // 随机
            // 先把低保放进去
            Arrays.fill(rs, MIN.toString());
    
            BigDecimal weightSum = BigDecimal.ZERO;
            BigDecimal redSum = BigDecimal.ZERO;
            BigDecimal[] weights = new BigDecimal[amount];
            // 随机
            for (int i=0; i<rs.length; i++){
                BigDecimal seed = new BigDecimal(new Random().nextInt(amount));
                weightSum = weightSum.add(seed);
                weights[i] = seed;
    
                // 循环最后一个后计算金额
                if(i == rs.length -1){
                    for(int j=0; j<rs.length; j++){
                        BigDecimal val = faceValue.multiply(weights[j].divide(weightSum,2, BigDecimal.ROUND_DOWN));
                        redSum = redSum.add(val);
                        rs[j] = val.add(MIN).toString();
                    }
                }
            }
    
            // 随机获取一个下标
            BigDecimal diff = faceValue.subtract(redSum);
            int index = new Random().nextInt(amount);
            rs[index] = String.valueOf(new BigDecimal(rs[index]).add(diff));
    
            return rs;
        }
    
    }
    
    展开全文
  • php固定红包 + 随机红包算法

    万次阅读 多人点赞 2016-11-20 12:39:33
    CleverCode最近接到一个需求,需要写一个固定红包 + 随机红包算法。 1 固定红包就是每个红包金额一样,有多少个就发多少个固定红包金额就行。 2 随机红包的需求是。比如红包总金额5元,需要发10个红包。随机范围是...

    1 需求

    CleverCode最近接到一个需求,需要写一个固定红包 + 随机红包算法。

    1 固定红包就是每个红包金额一样,有多少个就发多少个固定红包金额就行。

    2 随机红包的需求是。比如红包总金额5元,需要发10个红包。随机范围是 0.01到0.99;5元必需发完,金额需要有一定趋势的正态分布。(0.99可以任意指定,也可以是 avg * 2 - 0.01;比如avg = 5 / 10 = 0.5;(avg * 2 - 0.01 = 0.99))

     

    2 需求分析

    2.1 固定红包

     如果是固定红包,则算法是一条直线。t就是固定红包的额度。如图。
     f(x) = t;(1 <= x <= num)

     

    2.2 随机红包

    如果我们使用随机函数rand。rand(0.01,0.99);那么10次随机,如果最坏情况都是金额0.99,总金额就是9.9元。会超过5元。金额也会不正态分布。最后思考了一下借助与数学函数来当作随机红包的发生器,可以用抛物线,三角函数。最后选定了等腰三角线性函数。

     

    1 算法原理

    如果需要发红包总金额是totalMoney,红包个数是num个,金额范围是[min,max],线性方程如图。

    三个点的坐标:

    (x1,y1) =  (1,min)

      (x2,y2)  = (num/2,max)

      (x3,y3) = (num,min)

    确定的线性方程:

    $y = 1.0 * ($x - $x1) / ($x2 - $x1) * ($y2 - $y1) + $y1 ; (x1 <= x <= x2)
    $y = 1.0 * ($x - $x2) / ($x3 - $x2) * ($y3 - $y2) + $y2;  (x2 <= x <= x3)

    修数据:
    y(合)  = y1 + y2 + y3 +...... ynum;
    y(合)有可能 > totalMoney ,说明生成金额多了,需要修数据,则从(y1,y2,y3.....ynum)这些每次减少0.01。直到y(合) = totalMoney。
    y(合)有可能 < totalMoney ,说明生成金额少了,需要修数据,则从(y1,y2,y3.....ynum)这些每次加上0.01。直到y(合) = totalMoney。

     

    2 算法原理样例

    如果需要发红包总金额是11470,红包个数是7400个,金额范围是[0.01,3.09],线性方程如图。

    3 需求设计

    3.1 类图设计

     

    3.2 源码设计

     

    <?php
    /**
     * 随机红包+固定红包算法[策略模式]
     * copyright (c) 2016 http://blog.csdn.net/CleverCode
     */
    
    //配置传输数据DTO
    class OptionDTO
    {/*{{{*/
    
        //红包总金额
        public $totalMoney;
    
        //红包数量
        public $num;
    
        //范围开始
        public $rangeStart;
    
        //范围结算
        public $rangeEnd;
    
        //生成红包策略
        public $builderStrategy;
    
        //随机红包剩余规则
        public $randFormatType; //Can_Left:不修数据,可以有剩余;No_Left:不能有剩余
    
        public static function create($totalMoney,$num,$rangeStart,$rangEnd,
            $builderStrategy,$randFormatType = 'No_Left')
        {/*{{{*/
            $self = new self();
            $self->num = $num;
            $self->rangeStart = $rangeStart;
            $self->rangeEnd = $rangEnd;
            $self->totalMoney = $totalMoney;
            $self->builderStrategy = $builderStrategy;
            $self->randFormatType = $randFormatType;
            return $self; 
        }/*}}}*/
    
    }/*}}}*/
    
    //红包生成器接口
    interface IBuilderStrategy
    {/*{{{*/
        //创建红包
        public function create();    
        //设置配置
        public function setOption(OptionDTO $option); 
        //是否可以生成红包
        public function isCanBuilder();
        //生成红包函数
        public function fx($x);
    }/*}}}*/
    
    //固定等额红包策略
    class EqualPackageStrategy implements IBuilderStrategy
    {/*{{{*/
        //单个红包金额
        public $oneMoney;
    
        //数量
        public $num;
    
        public function __construct($option = null) 
        {
            if($option instanceof OptionDTO)
            {
                $this->setOption($option);
            }
        }
    
        public function setOption(OptionDTO $option)
        {
            $this->oneMoney = $option->rangeStart;
            $this->num = $option->num;
        }
    
        public function create() 
        {/*{{{*/
    
            $data = array();
            if(false == $this->isCanBuilder())
            {
                return $data;    
            }
    
            $data = array();
            if(false == is_int($this->num) || $this->num <= 0) 
            {
                return $data;    
            }
            for($i = 1;$i <= $this->num;$i++)
            {
                $data[$i] = $this->fx($i);
            }
            return $data;
        }/*}}}*/
        
        /**
         * 等额红包的方程是一条直线 
         * 
         * @param mixed $x 
         * @access public
         * @return void
         */
        public function fx($x) 
        {/*{{{*/
            return $this->oneMoney; 
        }/*}}}*/
    
        /**
         * 是否能固定红包 
         * 
         * @access public
         * @return void
         */
        public function isCanBuilder()
        {/*{{{*/
            if(false == is_int($this->num) || $this->num <= 0) 
            {
                return false;    
            }
    
            if(false ==  is_numeric($this->oneMoney) || $this->oneMoney <= 0)
            {
                return false;
            }
    
            //单个红包小于1分
            if($this->oneMoney < 0.01)
            {
                return false;
            }
            
            return true;
    
        }/*}}}*/
    
    
    }/*}}}*/
    
    //随机红包策略(三角形)
    class RandTrianglePackageStrategy implements IBuilderStrategy
    {/*{{{*/
        //总额
        public $totalMoney;
    
        //红包数量
        public $num;
    
        //随机红包最小值
        public $minMoney;
    
        //随机红包最大值
        public $maxMoney;
    
        //修数据方式:NO_LEFT: 红包总额 = 预算总额;CAN_LEFT: 红包总额 <= 预算总额
        public $formatType; 
    
        //预算剩余金额
        public $leftMoney;
    
    
        public function __construct($option = null) 
        {/*{{{*/
            if($option instanceof OptionDTO)
            {
                $this->setOption($option);
            }
        }/*}}}*/
    
        public function setOption(OptionDTO $option)
        {/*{{{*/
            $this->totalMoney = $option->totalMoney;
            $this->num = $option->num;
            $this->formatType = $option->randFormatType;
            $this->minMoney = $option->rangeStart;
            $this->maxMoney = $option->rangeEnd;
            $this->leftMoney = $this->totalMoney;
        }/*}}}*/
    
        /**
         * 创建随机红包 
         * 
         * @access public
         * @return void
         */
        public function create() 
        {/*{{{*/
            
            $data = array();
            if(false == $this->isCanBuilder())
            {
                return $data;    
            }
            
            $leftMoney = $this->leftMoney;
            for($i = 1;$i <= $this->num;$i++)
            {
                $data[$i] = $this->fx($i);
                $leftMoney = $leftMoney - $data[$i]; 
            }
    
            //修数据
            list($okLeftMoney,$okData) = $this->format($leftMoney,$data);
    
            //随机排序
            shuffle($okData);
            $this->leftMoney = $okLeftMoney;
    
            return $okData;
        }/*}}}*/
    
        /**
         * 是否能够发随机红包 
         * 
         * @access public
         * @return void
         */
        public function isCanBuilder()
        {/*{{{*/
            if(false == is_int($this->num) || $this->num <= 0) 
            {
                return false;    
            }
    
            if(false ==  is_numeric($this->totalMoney) || $this->totalMoney <= 0)
            {
                return false;
            }
    
            //均值
            $avgMoney = $this->totalMoney / 1.0 / $this->num;
            
            //均值小于最小值
            if($avgMoney < $this->minMoney )
            {
                return false;
            }
            
            return true;
    
        }/*}}}*/
    
        /**
         * 获取剩余金额 
         * 
         * @access public
         * @return void
         */
        public function getLeftMoney()
        {/*{{{*/
            return $this->leftMoney;
        }/*}}}*/
    
        /**
         * 随机红包生成函数。三角函数。[(1,0.01),($num/2,$avgMoney),($num,0.01)] 
         * 
         * @param mixed $x,1 <= $x <= $this->num; 
         * @access public
         * @return void
         */
        public function fx($x)
        {/*{{{*/
            
            if(false == $this->isCanBuilder())
            {
                return 0;
            }
    
            if($x < 1 || $x > $this->num)
            {
                return 0;
            }
            
            $x1 = 1;
            $y1 = $this->minMoney;
            
            //我的峰值
            $y2 = $this->maxMoney;
    
            //中间点
            $x2 = ceil($this->num /  1.0 / 2);
    
            //最后点
            $x3 = $this->num;
            $y3 = $this->minMoney;  
    
            //当x1,x2,x3都是1的时候(竖线)
            if($x1 == $x2 && $x2 == $x3)
            {
                return $y2;
            }
    
            // '/_\'三角形状的线性方程
            //'/'部分
            if($x1 != $x2 && $x >= $x1 && $x <= $x2)
            {
    
                $y = 1.0 * ($x - $x1) / ($x2 - $x1) * ($y2 - $y1) + $y1;  
                return number_format($y, 2, '.', '');
            }
    
            //'\'形状
            if($x2 != $x3 && $x >= $x2 && $x <= $x3)
            {
    
                $y = 1.0 * ($x - $x2) / ($x3 - $x2) * ($y3 - $y2) + $y2;  
                return number_format($y, 2, '.', '');
            }
            
            return 0;
    
    
        }/*}}}*/
    
        /**
         * 格式化修红包数据 
         * 
         * @param mixed $leftMoney 
         * @param array $data 
         * @access public
         * @return void
         */
        private function format($leftMoney,array $data)
        {/*{{{*/
    
            //不能发随机红包
            if(false == $this->isCanBuilder())
            {
                return array($leftMoney,$data);  
            }
            
            //红包剩余是0
            if(0 == $leftMoney)
            {
                return array($leftMoney,$data);  
            }
    
            //数组为空
            if(count($data) < 1)
            {
                return array($leftMoney,$data);  
            }
    
            //如果是可以有剩余,并且$leftMoney > 0
            if('Can_Left' == $this->formatType
              && $leftMoney > 0)
            {
                return array($leftMoney,$data);  
            }
    
    
            //我的峰值
            $myMax = $this->maxMoney;
    
            // 如果还有余钱,则尝试加到小红包里,如果加不进去,则尝试下一个。
            while($leftMoney > 0)
            {
                $found = 0;
                foreach($data as $key => $val) 
                {
                    //减少循环优化
                    if($leftMoney <= 0)
                    {
                        break;
                    }
    
                    //预判
                    $afterLeftMoney =  (double)$leftMoney - 0.01;
                    $afterVal = (double)$val + 0.01;
                    if( $afterLeftMoney >= 0  && $afterVal <= $myMax)
                    {
                        $found = 1;
                        $data[$key] = number_format($afterVal,2,'.','');
                        $leftMoney = $afterLeftMoney;
                        //精度
                        $leftMoney = number_format($leftMoney,2,'.','');
                    }
                }
    
                //如果没有可以加的红包,需要结束,否则死循环
                if($found == 0)
                {
                    break;
                }
            }
            //如果$leftMoney < 0 ,说明生成的红包超过预算了,需要减少部分红包金额
            while($leftMoney < 0)
            {
                $found = 0;
                foreach($data as $key => $val) 
                {
                    if($leftMoney >= 0)
                    {
                        break; 
                    }
                    //预判
                    
                    $afterLeftMoney =  (double)$leftMoney + 0.01;
                    $afterVal = (double)$val - 0.01;
                    if( $afterLeftMoney <= 0 && $afterVal >= $this->minMoney)
                    {
                        $found = 1;
                        $data[$key] = number_format($afterVal,2,'.','');
                        $leftMoney = $afterLeftMoney;
                        $leftMoney = number_format($leftMoney,2,'.','');
                    }
                }
                
                //如果一个减少的红包都没有的话,需要结束,否则死循环
                if($found == 0)
                {
                    break;
                }
            }
            return array($leftMoney,$data);  
        }/*}}}*/
    
    }/*}}}*/
    
    //维护策略的环境类
    class RedPackageBuilder
    {/*{{{*/
    
        // 实例  
        protected static $_instance = null;  
    
        /** 
         * Singleton instance(获取自己的实例) 
         * 
         * @return MemcacheOperate 
         */  
        public static function getInstance()
        {  /*{{{*/
            if (null === self::$_instance) 
            {  
                self::$_instance = new self();  
            }  
            return self::$_instance;  
        }  /*}}}*/
    
        /** 
         * 获取策略【使用反射】
         * 
         * @param string $type 类型 
         * @return void 
         */  
        public function getBuilderStrategy($type)
        {  /*{{{*/
            $class = $type.'PackageStrategy';
    
            if(class_exists($class))
            {
                return new $class();  
            }
            else
            {
                throw new Exception("{$class} 类不存在!");
            }
        }  /*}}}*/
    
        public function getRedPackageByDTO(OptionDTO $optionDTO) 
        {/*{{{*/
            //获取策略
            $builderStrategy = $this->getBuilderStrategy($optionDTO->builderStrategy);
    
            //设置参数
            $builderStrategy->setOption($optionDTO);
    
            return $builderStrategy->create();
        }/*}}}*/
        
    }/*}}}*/
    
    class Client
    {/*{{{*/
        public static function main($argv)
        {
            //固定红包
            $dto = OptionDTO::create(1000,10,100,100,'Equal');
            $data = RedPackageBuilder::getInstance()->getRedPackageByDTO($dto);
            //print_r($data);
    
            //随机红包[修数据]
            $dto = OptionDTO::create(5,10,0.01,0.99,'RandTriangle');
            $data = RedPackageBuilder::getInstance()->getRedPackageByDTO($dto);
            print_r($data);
    
            //随机红包[不修数据]
            $dto = OptionDTO::create(5,10,0.01,0.99,'RandTriangle','Can_Left');
            $data = RedPackageBuilder::getInstance()->getRedPackageByDTO($dto);
            //print_r($data);
            
        }
    }/*}}}*/
    
    Client::main($argv);
    

     

     

     

    3.3 结果展示

     

     1 固定红包

    //固定红包
    $dto = OptionDTO::create(1000,10,100,100,'Equal');
    $data = RedPackageBuilder::getInstance()->getRedPackageByDTO($dto);
    print_r($data);

     

    2 随机红包(修数据)

    这里使用了php的随机排序函数, shuffle($okData),所以看到的结果不是线性的,这个结果更加随机性。

     //随机红包[修数据]
     $dto = OptionDTO::create(5,10,0.01,0.99,'RandTriangle');
     $data = RedPackageBuilder::getInstance()->getRedPackageByDTO($dto);
     print_r($data);

     

    3 随机红包(不修数据)

    不修数据,1 和num的金额是最小值0.01。

     //随机红包[不修数据]
     $dto = OptionDTO::create(5,10,0.01,0.99,'RandTriangle','Can_Left');
     $data = RedPackageBuilder::getInstance()->getRedPackageByDTO($dto);
     print_r($data);

    技术交流

    CleverCode是一名架构师,技术交流,咨询问题,请加CleverCode创建的qq群(架构师俱乐部):517133582。加群和腾讯,阿里,百度,新浪等公司的架构师交流。【架构师俱乐部】宗旨:帮助你成长为架构师!

     

     

    展开全文
  • 主要介绍了PHP实现的随机红包算法,结合实例形式分析了php随机红包算法的原理、实现方法与相关注意事项,需要的朋友可以参考下
  • PHP-随机红包算法

    2018-05-11 09:47:22
    PHP优化随机红包算法。用PHP实现微信QQ随机红包值。高度还原随机值,不会出现过大或者过小,可以拿去参考
  • 随机红包算法,基于c语言,emm,自己写的,基础思想,二倍均值法,有不足欢迎指正,随机红包算法,基于c语言。
  • 主要介绍了java 微信随机红包算法的相关资料,并附实例代码,需要的朋友可以参考下
  • 随机红包算法 简单模仿微信发送随机红包写的算法 /** * 随机红包算法 * $mony分钱随机发给$count个人,$height越大,随机金额大小分化越大 */ function rand_redpack($mony,$count = 300, $height = 10){ if($...

    随机红包算法


    在这里插入图片描述

    简单模仿微信发送随机红包写的算法

    
    /**
     * 随机红包算法
     * $mony分钱随机发给$count个人,$height越大,随机金额大小分化越大
     */
    function rand_redpack($mony,$count = 30, $height = 4){
        if($mony < $count) return false; //不够分
        if($height <= 0) return false; //$height只能大于或等于0
        $arr = [];
        for ($x=0; $x<$count; $x++) $arr[] = 1;
        $restMony = $mony - $count;
        $roll = function($arr, $restMony) use (&$roll, $height) { //匿名递归写法
            if($restMony === 0) return $arr;
            $index = rand(0,count($arr)-1);
            $passe = ceil($height*round($restMony/count($arr)));
            $spend = $restMony>=$passe ? rand(1, $passe) : rand(1, $restMony);
            $arr[$index] += $spend;
            return $roll($arr, $restMony-$spend);
        };
        return $roll($arr, $restMony);
    };
    
    
    //假如我们把50元红包发给30个人
    rand_redpack(5000, 30, 4);
    结果
    array:30 [
      0 => 99
      1 => 176
      2 => 14
      3 => 160
      4 => 231
      5 => 65
      6 => 178
      7 => 36
      8 => 1
      9 => 95
      10 => 43
      11 => 23
      12 => 92
      13 => 220
      14 => 16
      15 => 638
      16 => 49
      17 => 1
      18 => 528
      19 => 19
      20 => 2
      21 => 505
      22 => 620
      23 => 41
      24 => 9
      25 => 451
      26 => 181
      27 => 55
      28 => 104
      29 => 348
    ]
    
    rand_redpack(5000, 30, 0.1);
    array:30 [
      0 => 194
      1 => 154
      2 => 134
      3 => 130
      4 => 177
      5 => 178
      6 => 178
      7 => 122
      8 => 174
      9 => 201
      10 => 154
      11 => 176
      12 => 164
      13 => 211
      14 => 146
      15 => 157
      16 => 233
      17 => 198
      18 => 121
      19 => 189
      20 => 108
      21 => 99
      22 => 155
      23 => 165
      24 => 163
      25 => 185
      26 => 171
      27 => 162
      28 => 230
      29 => 171
    ]
    
    展开全文
  • PHP 随机红包算法

    2019-02-22 16:00:50
    php 随机红包算法 固定红包就不用说了,等额发就行了。 目前主要说的是随机红包 直接上代码 &lt;?php $money = 1; // 红包大小 $num = 100; // 红包个数 $min = 0.01; // 单个红包最低金额 $ret = lottery($...

    php 随机红包算法

    固定红包就不用说了,等额发就行了。 目前主要说的是随机红包 直接上代码

    <?php
    
    $money = 1;    // 红包大小
    $num   = 100;      // 红包个数
    $min   = 0.01; // 单个红包最低金额
    
    $ret = lottery($money, $num, $min);
    if (! is_array($ret)) {
        exit($ret.PHP_EOL);
    }
    
    echo '手气最佳:'.max($ret).PHP_EOL;
    echo '手气最差:'.min($ret).PHP_EOL;
    echo PHP_EOL;
    
    print_r($ret);
    
    //----------------------------------------------------------------------
    
    // 产生一个随机浮点数
    function random_float($min = 0, $max = 1)
    {
        return round($min + mt_rand() / mt_getrandmax() * ($max - $min), 2);
    }
    
    // 微信随机红包模拟算法
    function lottery($sum_money, $num, $min_money = 0.01)
    {
        if ($sum_money < $num * $min_money) {
            return '钱不够';
        }
    
        $list = [];
        for ($i = 1; $i <= $num; $i++) {
            // 剩余的可分配金额,需要确保剩下的人每人都至少可以拿到保底的钱
            $remain = $sum_money - array_sum($list) - ($num - $i + 1) * $min_money;
    
            if ($i < $num) {  // 前面的人随机获得
                // 每轮抽取的金额范围:0 至 剩余金额平均值的两倍
                $get = random_float(0, $remain / ($num - $i + 1) * 2);
            } else {  // 最后一个人拿全部剩下的
                $get = $remain;
            }
    
            // 最后再将每个人保底的钱加上
            $list[] = round(round($get, 2)   + $min_money, 2);
        }
    
        return $list;
    }
    
    展开全文
  • js 随机红包算法

    2019-08-08 10:22:50
    1.经过一天多的时间,踏过无数bug与辛酸,最终在这个阳光...// 生成剩余金额(随机红包算法) randownMoney:function(){ // 填写的总额 var totalMoney=0; // 剩余总额 var dediMoney=0; // 未填数组 ...
  • 随机红包算法就是给定一个具体的红包金额,具体的红包个数,还有给定红包的最大金额和最小金额,按照业务可以分成两种,一种是预先生成,一种是实时生成 1、预先生成 public function getBonus($money, $num, $...
  • CleverCode最近接到一个需求,需要写一个固定红包 + 随机红包算法。 1 固定红包就是每个红包金额一样,有多少个就发多少个固定红包金额就行。 2 随机红包的需求是。比如红包总金额5元,需要发10个红包。随机范围是...
  • * 简易随机红包算法 * @param amt 红包金额 * @param count 红包数量 */ public static void sendRandomBonus(BigDecimal amt, int count) { //转为两位小数表示 amt = amt.setScale(2); ...
  • * 随机红包+固定红包算法[策略模式] * copyright (c) 2016 http://blog.csdn.net/CleverCode */ //配置传输数据DTO class RangeDto { //红包总金额 public $totalMoney; //红包数量 public $n...
  • php 随机红包算法

    2019-04-28 11:01:00
    <?php /** * 红包分配算法 * * example * $coupon = new Coupon(200, 5); * $res = $coupon->handle(); * print_r($res); * @author Flc <2018-04-06 20:09:53>...
  • PHP随机红包算法

    2017-01-14 14:32:00
    2017年1月14日 14:19:14 星期六 一, 整体设计 ...二, 红包算法 简便起见, 红包金额用整数表示, 假设每个红包里边有x个糖豆, 每个人最少一个豆 一种: 每个红包的最大金额是: (剩余金额/剩余红包数)*...
  • 微信随机红包算法

    2016-11-23 23:09:34
    基本思路是这样的:首先算出红包的平均值,再生产小于这个平均值的随机数,红包发送后,红包总金额需要相应减少,同时重新计算这个平均值,直到最后一个红包时,把所有的剩余金额塞进去。 public static double ...
  • 今天面到的算法题挺有意思,是要我写一个...这其实就是一个随机红包的问题,这个思路就是要注意这n部分要一份一分的分开生成,我们需要确定的就是每一份的上下限是什么。 上限:math.min{max-val,m - (n - ni)*min_v
  • 本文主要介绍了php实现的微信红包算法,以实例形式分析了拼手气红包的相关随机算法技巧。希望对大家有所帮助。具体如下:最近一直在微信群里体验红包功能,红包类型有两种:1. 普通红包2. 拼手气红包普通红包就不用...
  • 随机红包算法(Java)

    2016-08-18 15:22:00
    .println("第"+i+"个红包:"+money+",余额为:"+total+"元"); } System. out .println("第"+num+"个红包:"+total+",余额为:0元"); } void zb(){ for ( int a=0;a;a++){ if (a % 1000== 0) ...
  • 微信红包的架构设计简介: 原文:https://www.zybuluo.com/yulin718/note/93148 @来源于QCon某高可用架构群整理,整理朱玉华。 背景:有某个朋友在朋友圈咨询微信红包的架构,于是乎有了下面的文字(有误请提出...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 439
精华内容 175
关键字:

随机红包算法