关于微信红包简单算法 PHP Edition

本文模拟了一种微信抢红包的游戏算法,通过PHP代码实现并分析了不同末位数出现的概率,结果显示各数字概率接近90%。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这两天在微信群中玩了一个抢红包游戏,游戏规则如下:
1. 参与者可以选择发红包或者抢红包,红包需为30-100之间的整10倍数,每个红包人数为9人。
2. 发红包者可以设定一个0-9间任意末尾数为炸弹,凡是领完红包金额末尾为该数字的,需要返还发红包者1.2倍的金额,其余的正常领取红包。
例如30-3,如果有领红包者为5.03、0.33、6.73之类以3为末尾的红包金额,就需要返还发红包者30*1.2=36元。

我大致看了一下知乎上关于微信的算法,本来是想total-0.01*(n-1)作为可领取红包总金额,但是实际操作了一下发现实际红包差额太大,将随机金额数缩小了范围,比如100元10人的红包 上限就定在(100/10)*2,后来有发现最后2个红包可能会超出总金额,又对倒数第二个红包加了限制,如下是php代码,运算结果也会贴在下方。

代码不是很优雅,望见谅

<?php

class RedPacket{
    public $total = 30 ;   //总金额
    public $least = 0.01;  //人均最少
    public $num = 9;       //红包人数
    public $sum = 0;       //可红包领取金额
    public static $a0 = 0;      //0
    public static $a1 = 0;      //1
    public static $a2 = 0;      //2
    public static $a3 = 0;      //3
    public static $a4 = 0;      //4
    public static $a5 = 0;      //5
    public static $a6 = 0;      //6
    public static $a7 = 0;      //7
    public static $a8 = 0;      //8
    public static $a9 = 0;      //9

    public function SendRedPacket(){
        //循环9次领取红包
        for($i=1;$i<10;$i++) {
            //计算可发红包金额 每人最少0.01元
            $this->sum = $this->total - ($this->num - $i) * $this->least;

            //判断是否是最后一个红包
            if ($i < 9) {
                $redpacket = rand(1, ($this->sum * 100) / ($this->num - $i) * 2) / 100;
                //判断发出的红包总计如果超出总和,则重新计算
                if (($this->total - $redpacket) < 0) {
                    $redpacket = rand(1, ($this->sum * 100) / ($this->num - $i)) / 100;
                }
                $this->total -= $redpacket;
            } else {
                //最后一个红包就是剩余金额
                $redpacket = $this->total;
                $this->total = 30;
            }
            $red = sprintf('%.2f', $redpacket);
            //截取红包金额末位
            $number = substr($red, -1, 1);
            switch ($number) {
                case 0:
                    self::$a0++;
                    break;
                case 1:
                    self::$a1++;
                    break;
                case 2:
                    self::$a2++;
                    break;
                case 3:
                    self::$a3++;
                    break;
                case 4:
                    self::$a4++;
                    break;
                case 5:
                    self::$a5++;
                    break;
                case 6:
                    self::$a6++;
                    break;
                case 7:
                    self::$a7++;
                    break;
                case 8:
                    self::$a8++;
                    break;
                case 9:
                    self::$a9++;
                    break;
            }
        }
    }
    public function Show(){
        //显示各数字概率
        echo '0: '.((self::$a0)).'%'."<br/>".
            '1: '.((self::$a1)).'%'."<br/>".
            '2: '.((self::$a2)).'%'."<br/>".
            '3: '.((self::$a3)).'%'."<br/>".
            '4: '.((self::$a4)).'%'."<br/>".
            '5: '.((self::$a5)).'%'."<br/>".
            '6: '.((self::$a6)).'%'."<br/>".
            '7: '.((self::$a7)).'%'."<br/>".
            '8: '.((self::$a8)).'%'."<br/>".
            '9: '.((self::$a9)).'%'."<br/>";
    }
}
$red = new RedPacket();
//设置发包次数
for($i=0;$i<100000;$i++){
$red->SendRedPacket();
}
//展示红包数
$red->Show();

以下是我循环10万次结果总结出的数据:

0: 88.405%
1: 91.235%
2: 91.51%
3: 90.684%
4: 90.814%
5: 89.692%
6: 90.132%
7: 89.337%
8: 89.333%
9: 88.858%

以上数据仅根据我的算法得出,实际和微信的还有差距,总体每个数字的概率还是趋近于90%,可能还是因为算法问题会有部分差异。

感觉在php中,对于算法的需求并没有那么大,所以偶尔敲敲玩玩还是蛮不错的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值