返回首页 - Notes - 2018

模拟微信随机红包算法


算法实现

#!/usr/bin/env php
<?php

/*
 * 微信随机红包算法模拟
 */

$money = round(@$argv[1], 2) ?: 0;  // 红包大小
$num   = intval(@$argv[2]) ?: 1;    // 抢的人数

if ($money < $num * 0.01) {
    exit('老板,钱不够发'.PHP_EOL);
}

function randomFloat($min = 0, $max = 1)
{
    return round($min + mt_rand() / mt_getrandmax() * ($max - $min), 2);
}

$list = [];
for ($i = 1; $i <= $num; $i++) {
    // 剩余的可分配金额,需要确保剩下的人每人都至少可以拿到1分钱
    $remain = $money - array_sum($list) - ($num - $i + 1) * 0.01;

    if ($i < $num) {  // 前面的人随机获得
        // 每轮抽取的金额范围:0 至 剩余金额平均值的两倍
        $get = randomFloat(0, $remain / ($num - $i + 1) * 2);
    } else {  // 最后一个人拿全部剩下的
        $get = $remain;
    }

    // 最后再将每个人保底的1分钱加上
    $list[] = round($get, 2) + 0.01;
}

print_r($list);
echo '手气最佳:'.max($list).PHP_EOL;
echo '手气最差:'.min($list).PHP_EOL;

运行示例

./red_packet 200 10

Array
(
    [0] => 28.93
    [1] => 22.05
    [2] => 24.38
    [3] => 14.16
    [4] => 23.7
    [5] => 22
    [6] => 6.78
    [7] => 37.69
    [8] => 8.36
    [9] => 11.95
)
手气最佳:37.69
手气最差:6.78

date:2018-05-08