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;
}
相关推荐
caimouse10 分钟前
Reactos 第 5 章 进程与线程 — 5.3 系统调用 NtCreateProcess()
服务器·开发语言
ch.ju15 分钟前
Java程序设计(第3版)第四章——继承的调用
java·开发语言
W_LuYi18526 分钟前
Tauri + Rust + Vue 3 打造极速轻量桌面应用
java·开发语言·vue.js·rust
少司府26 分钟前
C++进阶:红黑树
开发语言·数据结构·c++·b树·二叉树·红黑树
特种加菲猫43 分钟前
哈希表的实现
开发语言·c++
C+-C资深大佬44 分钟前
Python 新手学习指南
开发语言·python
小张小张爱学习1 小时前
Java基础面试题
java·开发语言
Drone_xjw1 小时前
Qt国际化多语言配置详解-入门到精通
开发语言·qt·命令模式
爱吃提升1 小时前
Python 多线程 threading + 多进程 multiprocessing 完整实操教程
开发语言·python
不会C语言的男孩1 小时前
C++ Primer 第18章:用于大型程序的工具
开发语言·c++