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;
}
相关推荐
前端小咸鱼一条21 分钟前
16.迭代器 和 生成器
开发语言·前端·javascript
小陈工29 分钟前
2026年3月31日技术资讯洞察:AI智能体安全、异步编程突破与Python运行时演进
开发语言·jvm·数据库·人工智能·python·安全·oracle
ok_hahaha1 小时前
java从头开始-黑马点评-Redission
java·开发语言
无巧不成书02181 小时前
Java面向对象零基础实战:从Employee类吃透自定义类核心,掌握封装精髓
java·开发语言·java入门·面向对象·自定义类·employee类·java核心技术
跃上青空1 小时前
Java如何优雅的使用fastjson2进行枚举序列化/反序列化,欢迎探讨
java·开发语言
Leo655351 小时前
动态透视报表 + 查询接口 + Excel导出
开发语言·windows·python
BioRunYiXue2 小时前
Nature Methods:CellVoyager 自主 AI 智能体开启生物数据分析新时代
大数据·开发语言·前端·javascript·人工智能·数据挖掘·数据分析
kcuwu.3 小时前
Python面向对象:封装、继承、多态
开发语言·python
一定要AK3 小时前
Java流程控制
java·开发语言·笔记