欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

微信红包算法

程序员文章站 2022-05-30 10:36:34
...

之前一直在思考关于微信的红包算法是如何实现的,就在网上找了很多相关的技术但大都是java写的,了解了其中的原理和思路就自己用php搞搞玩,下面大概总结了2种方法,请大家参考一下:

第一种:二倍均值法

第二种:线段分割法

下面先用2种方法去实现第一种

1.1 方法----------------------------

        $money = 100;  //100元

        $peoples = 10; //10人参与

        $min = 1;//最小金额 1元

        

        $rest_amount = $money;

        $rest_peoples = $peoples;

        $getAmount = 0;

        for($i=0;$i<$peoples;$i++){

            //随机范围:[1,剩余人均金额的两倍),左闭右开

            $lastOne = $peoples - 1;

            if($i != $lastOne){

                

                $getAmount = rand($min, ($rest_amount / $rest_peoples * 2));  //精华

                $res[$i] = $getAmount;

                $rest_amount = $rest_amount - $getAmount;

                $rest_peoples--;

            }else{

                $res[$i] = $rest_amount;  //这边跟他们的不一样(最后一个人是剩余金额,防止不足或超出总金额)

            }

        }

        

        echo '<pre>';

        print_r($res);

        echo array_sum($res);

        die;

大家看一下结果:

结果1

微信红包算法
            
    
    博客分类: 技术总结 日常所思 
 结果2:

微信红包算法
            
    
    博客分类: 技术总结 日常所思 
 结论:感觉随机的结果没微信初始的好;再看下面的方法:

        $total=100;//红包总额 

        $num=10;// 分成10个红包,支持10人随机领取

        $min=1;//每个人最少能收到1元 

         

        $data = [];

        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; 

            $data[$i] = $money;

        } 

        $data[$num] = $total;

        

        

        echo '<pre>';

        print_r($data);

        echo array_sum($data);

        die;

结果如下:

微信红包算法
            
    
    博客分类: 技术总结 日常所思 
 或者:

微信红包算法
            
    
    博客分类: 技术总结 日常所思 
 貌似这种结果还算靠近微信的结果,很少出现1元最低的情况;

//----------------第二种方法(线段分割法)--------------

我们可以把红包总金额想象成一条很长的线段,而每个人抢到的金额,则是这条主线段所拆分出的若干子线段。由“切割点”来决定。当N个人一起抢红包的时候,就需要确定N-1个切割点。

因此,当N个人一起抢总金额为M的红包时,我们需要做N-1次随机运算,以此确定N-1个切割点。随机的范围区间是(1, M)。

当所有切割点确定以后,子线段的长度也随之确定。这样每个人来抢红包的时候,只需要顺次领取与子线段长度等价的红包金额即可。

 

        $total=100;//红包总额

        $num=10;// 分成10个红包,支持10人随机领取

        $min=1;//每个人最少能收到1元

         

        $data = $money = [];

        for ($i=0;$i<$num;$i++)

        {

            $data[$i] = mt_rand($min,$total);

        }

        $sum = array_sum($data);

        $last = $num-1;

        for($k=0;$k<$last;$k++){ //0~8

            $money[$k] = round(($data[$k] / $sum) * $total,2);

        }

        

        $money[$last] = $total - array_sum($money);

        

        echo '<pre>';

        print_r($data);

        echo '<pre>';

        print_r($money);

        echo array_sum($money);

        die;

 结果如下:

微信红包算法
            
    
    博客分类: 技术总结 日常所思 
 或者

微信红包算法
            
    
    博客分类: 技术总结 日常所思 
 这个线段分割法感觉数据随机的还凑合,目前就是这两种方法,如有不足请大家多多指教,共同进步,

谢谢

 

 

  • 微信红包算法
            
    
    博客分类: 技术总结 日常所思 
  • 大小: 1.7 KB
  • 微信红包算法
            
    
    博客分类: 技术总结 日常所思 
  • 大小: 1.7 KB
  • 微信红包算法
            
    
    博客分类: 技术总结 日常所思 
  • 大小: 2.1 KB
  • 微信红包算法
            
    
    博客分类: 技术总结 日常所思 
  • 大小: 2 KB
  • 微信红包算法
            
    
    博客分类: 技术总结 日常所思 
  • 大小: 4.1 KB
  • 微信红包算法
            
    
    博客分类: 技术总结 日常所思 
  • 大小: 3.9 KB
相关标签: 日常所思