php 随机红包算法
<?php /**
* 红包分配算法
*
* example
* $coupon = new Coupon(200, 5);
* $res = $coupon->handle();
* print_r($res);
* @author Flc <2018-04-06 20:09:53>
* @see http://flc.ren | http://flc.io | https://github.com/flc1125
*/
class Coupon
{
/**
* 红包金额
* @var float
*/
protected $amount; /**
* 红包个数
* @var int
*/
protected $num; /**
* 领取的红包最小金额
* @var float
*/
protected $coupon_min; /**
* 红包分配结果
* @var array
*/
protected $items = []; /**
* 初始化
* @param float $amount 红包金额(单位:元)最多保留2位小数
* @param int $num 红包个数
* @param float $coupon_min 每个至少领取的红包金额
*/
public function __construct($amount, $num = 1, $coupon_min = 0.01)
{
$this->amount = $amount;
$this->num = $num;
$this->coupon_min = $coupon_min;
} /**
* 处理返回
* @return array
*/
public function handle()
{
// A. 验证
if ($this->amount < $validAmount = $this->coupon_min * $this->num) {
throw new Exception('红包总金额必须≥'.$validAmount.'元');
} // B. 分配红包
$this->apportion(); return [
'items' => $this->items,
];
} /**
* 分配红包
*/
protected function apportion()
{
$num = $this->num; // 剩余可分配的红包个数
$amount = $this->amount; //剩余可领取的红包金额 while ($num >= 1) {
// 剩余一个的时候,直接取剩余红包
if ($num == 1) {
$coupon_amount = $this->decimal_number($amount);
} else {
$avg_amount = $this->decimal_number($amount / $num); // 剩余的红包的平均金额 $coupon_amount = $this->decimal_number(
$this->calcCouponAmount($avg_amount, $amount, $num)
);
}
$this->items[] = $coupon_amount; // 追加分配 $amount -= $coupon_amount;
--$num;
} shuffle($this->items); //随机打乱
} /**
* 计算分配的红包金额
*
* @param float $avg_amount 每次计算的平均金额
* @param float $amount 剩余可领取金额
* @param int $num 剩余可领取的红包个数
* @return float
*/
protected function calcCouponAmount($avg_amount, $amount, $num)
{
// 如果平均金额小于等于最低金额,则直接返回最低金额
if ($avg_amount <= $this->coupon_min) {
return $this->coupon_min;
} // 浮动计算
$coupon_amount = $this->decimal_number($avg_amount * (1 + $this->apportionRandRatio())); // 如果低于最低金额或超过可领取的最大金额,则重新获取
if ($coupon_amount < $this->coupon_min
|| $coupon_amount > $this->calcCouponAmountMax($amount, $num)
) {
return $this->calcCouponAmount($avg_amount, $amount, $num);
} return $coupon_amount;
} /**
* 计算分配的红包金额-可领取的最大金额
* @param float $amount
* @param int $num
*/
protected function calcCouponAmountMax($amount, $num)
{
return $this->coupon_min + $amount - $num * $this->coupon_min;
} /**
* 红包金额浮动比例
*/
protected function apportionRandRatio()
{
// 60%机率获取剩余平均值的大幅度红包(可能正数、可能负数)
if (rand(1, 100) <= 60) {
return rand(-70, 70) / 100; // 上下幅度70%
} return rand(-30, 30) / 100; // 其他情况,上下浮动30%;
} /**
* 格式化金额,保留2位
* @param float $amount
* @return float
*/
protected function decimal_number($amount)
{
return sprintf('%01.2f', round($amount, 2));
} } // 例子
$price_total = 0;
$total = $surplus_total = 30;
$max_num = $surplus_num = 8;
echo "总共{$total}元,随机生成{$max_num}个红包".'</br>'; for($i=0;$i<$max_num;$i++){
$coupon = new Coupon($surplus_total, $surplus_num, 0.01);
$res = $coupon->handle();
$money = $res['items'][0];
$price_total += $money;
$surplus_total = bcsub($surplus_total, $money, 2); //解决高精度问题
echo '第'.($i+1).'个随机红包:'.$money.'还剩下'.($surplus_total).'元'.'<br>';
$surplus_num--;
}
示例演示:

php 随机红包算法的更多相关文章
- PHP实现微信随机红包算法和微信红包的架构设计简介
微信红包的架构设计简介: 原文:https://www.zybuluo.com/yulin718/note/93148 @来源于QCon某高可用架构群整理,整理朱玉华. 背景:有某个朋友在朋友圈咨询微 ...
- PHP随机红包算法
2017年1月14日 14:19:14 星期六 一, 整体设计 算法有很多种, 可以自行选择, 主要的"架构" 是这样的, 用redis decr()命令去限流, 用mysql去记 ...
- php 固定红包 + 随机红包算法
<?php /** * 随机红包+固定红包算法[策略模式] * copyright (c) 2016 http://blog.csdn.net/CleverCode */ //配置传输数据DTO ...
- C# 随机红包算法
static void Main(string[] args) { ; ; double minAmount = 0.01; Random r = new Random(); ; i < num ...
- 微信红包随机生成算法(PHP版)
/** * 求一个数的平方 * @param $n */ function sqr($n){ return $n*$n; } /** * 生产min和max之间的随机数,但是概率不是平均的,从min到 ...
- 微信红包算法TEST
1.基本算法 设定总金额为10元,有N个人随机领取:N=1 则红包金额=X元: N=2 为保证第二个红包可以正常发出,第一个红包金额=0.01至9.99之间的某个随机数 第二个红包=10-第一个红包金 ...
- PHP实现微信红包算法和微信红包的架构设计简介
微信红包的架构设计简介: 原文:https://www.zybuluo.com/yulin718/note/93148 @来源于QCon某高可用架构群整理,整理朱玉华. 背景:有某个朋友在朋友圈咨询微 ...
- php红包算法函数[优化]
php红包算法 <?php header("Content-Type: text/html;charset=utf-8");//输出不乱码,你懂的 $total=10000; ...
- php微信红包算法
微信红包算法.php /**生成红包的函数*/ function getRandMoney($totalMoney, $totalPeople=2, $miniMoney=1){ $randRemai ...
随机推荐
- MyCP-实现文件的复制以及进制转换
MyCP 一.设计思路 确定MyCP的要求 根据需求可知MyCP需要实现类似Linux下cp XXX1 XXX2的功能,且需要支持两个参数: java MyCP -tx XXX1.txt XXX2.b ...
- iOS UIView 选择性倒角
有些APP中会有卡券,卡券做成了选择性倒角,例如左上,右上倒角.非常美观.看一下iOS的实现: #import "Masonry.h" @interface WJWDaojiaoV ...
- python to shell vimdiff
目录 #!/bin/python3 import os import sys if(len(sys.argv) != 3): exit ("Usage: argv1:fullPath.txt ...
- 提取一个txt 文档中含指定字符串的所有行
将一个txt 文档中含指定字符串内容的所有行提取出来并保存至新的txt文档中 例如,要提取 1.txt 中所有包含”aaa” 的行的内容 只需在此文件夹中新建一个bat文件,输入以下代码,双击运行,便 ...
- python3 编码解码
字符换算 比特(bit) 计算机最小的存储单位 字节(byte) 1 bit = 1 位 8 bit = 1 byte 1024 bytes = 1 kb 1024 kb = 1 mb 1024 mb ...
- Vue.js——快速入门Vuex
一. 什么是Vuex? Vuex是一个专门为Vue.js应用程序开发的状态管理模式, 它采用集中式存储管理所有组件的公共状态, 并以相应的规则保证状态以一种可预测的方式发生变化. 上图中绿色虚线包裹起 ...
- Kali Hydra SSL issue, xHydra (GUI version of Hydra) works just fine
First find the source code. (https://is.gd/LlS5Sy) - Example search Once located you must download i ...
- Python第3次作业--李珠霞
习题1: **1.初始化一个数据集,包括5-10位同学的成绩数据(数据类型不限),数据格式如下: **学号 姓名 Java C语言 Python2017XXXX 小白 87 68 922017XXXX ...
- JavaScript实现RSA加解密
在GitHub上找到jsencrypt.js对RSA加解密的工具文件,地址分别是:https://github.com/travist/jsencrypt和https://github.com/ope ...
- .NET中结构和类的区别
最近在学习Swift语言,看到了枚举这一章,Swift可以支持在枚举中定义方法...于是想到了回顾一下.NET中枚举.结构.类之间区别. 枚举在.NET较为简单,这里就不作比较,只谈谈结构和类. 1. ...