php 随机红包数生成

无论哪种实现方式,随机红包都要遵守几个核心约束(这是和单纯随机数最大的区别):

  1. 总金额固定(比如 100 元分 10 个红包);
  2. 每个红包金额非空(至少 0.01 元,避免分到 0);
  3. 金额随机且符合 "拼手气" 特性(有人多有人少,而非平均);
  4. 所有红包金额之和严格等于总金额。
php 复制代码
/**
 * 随机分配红包金额.
 *
 * @param float|string $totalMoney 总金额(元)
 * @param int          $totalTimes 总次数
 * @param float|string $minMoney   单次最小值(元)
 * @param float|string $maxMoney   单次最大值(元)
 *
 * @return array|false 包含每次红包金额的数组(保留两位小数)|false 参数错误时返回false
 */
function random_red_packet($totalMoney, $totalTimes, $minMoney, $maxMoney)
{
    // 转换为分进行计算,避免浮点数精度问题
    $totalMoneyCent = (int) bcmul($totalMoney, 100);
    $minMoneyCent = (int) bcmul($minMoney, 100);
    $maxMoneyCent = (int) bcmul($maxMoney, 100);

    // 参数合法性校验
    if (
        $totalTimes <= 0
        || $minMoneyCent <= 0
        || $maxMoneyCent < $minMoneyCent
        || $totalMoneyCent < $totalTimes * $minMoneyCent // 总金额不足以分配最小值
        || $totalMoneyCent > $totalTimes * $maxMoneyCent    // 总金额超过最大值总和
    ) {
        return false;
    }

    $redPackets = [];
    $remainingCent = $totalMoneyCent;
    $remainingTimes = $totalTimes;

    for ($i = 0; $i < $totalTimes; ++$i) {
        // 最后一次直接分配剩余金额
        if (1 == $remainingTimes) {
            $currentCent = $remainingCent;
        } else {
            // 计算当前可分配的最大金额:不超过单红包最大值,且剩余次数能满足最小值
            $maxCurrentCent = min(
                $maxMoneyCent,
                $remainingCent - ($remainingTimes - 1) * $minMoneyCent
            );
            // 随机生成当前红包金额(在最小值和最大可分配金额之间)
            $currentCent = mt_rand($minMoneyCent, $maxCurrentCent);
        }

        // 转换为元并保留两位小数
        $redPackets[] = bcdiv($currentCent, 100, 2);

        // 更新剩余金额和次数
        $remainingCent = bcsub($remainingCent, $currentCent, 2);
        --$remainingTimes;
    }

    // 打乱数组(可选,模拟随机顺序)
    shuffle($redPackets);

    return $redPackets;
}
相关推荐
Pniubi几秒前
HashMap扩容全流程
java·开发语言·数据结构
白杨尚青2 小时前
C++进阶篇(二):多态——虚函数、重写、虚函数表与三个经典坑(附完整代码仓库)
开发语言·c++·多态·虚函数·重写·动态绑定
WJ.Polar20 小时前
Java封装、继承、多态
java·开发语言
摇滚侠20 小时前
Java 中如何表示负数,有符号和无符号的区别,补码的计算规则,char byte short int long 的范围
java·开发语言
weixin_3077791320 小时前
C++代码实现MATLAB中的fitrtree函数功能
开发语言·c++·算法·matlab
爱读书的小胖20 小时前
Codewars:Rot13(C)解题分析
c语言·开发语言
鸽鸽程序猿21 小时前
【项目】【在线判题系统】b端题目增删改
开发语言·python
Lhappy嘻嘻21 小时前
读懂 JVM:内存模型、类加载机制、分代回收
java·开发语言·jvm
weixin_307779131 天前
C++代码实现MATLAB中的spectralcluster函数功能
开发语言·c++·算法·matlab
鸽鸽程序猿1 天前
【项目】【在线判题系统】c端:竞赛报名
c语言·开发语言