场景: 一共10元,5个用户抢红包,最低抢 0.01元
运用内置方法
array_pad(array , int size , value) 把数组长度变为 szie ,填充值为value , rand(int min , int max) 返回一个在min ~ max 之间的整数,包含min,max round(num , size , mode) 保留两位小数
round(1.23222 , 2) 返回 1.23
php代码
方法一:
思路:
1、先处理临界值
2、根据抢红包人数进行循环,每人只能获取一个随机数,该随机数则为红包的金额
/**
* 发红包
* 10元发给5个用户,随机获取金额(最低0.01元)
* @param float $money 红包总金额
* @param int $people_num 用户人数
*/
function sendRedPackets(float $money , int $people_num = 1):array
{
// 生成 0 到1000 的随机数 ,并且减去 用户数量,确保每个用户最低为 0.01元
$arr = []; // 存生成的随机数
$sum = round($money ,2) *100; // 一共多少分钱
if($sum == $people_num){
// 钱和人数刚好满足 每人 0.01元
return array_pad([] , $people_num , 0.01);
}elseif($sum < $people_num){
// 钱不够分
return [];
}elseif($people_num == 1){
// 只有一个人 ,直接返回金额
return [$money];
}
for ($i=0; $i < $people_num; $i++) {
if($i == $people_num -1 ){
// 最后一个人,不需要才分了
$arr[] = $sum/100;
}else{
// 确保每个人最低为0.01
$rand_num = rand(1 , $sum - ($people_num - $i));
$sum = $sum - $rand_num;
$arr[] = $rand_num/100;
}
}
return $arr;
}
方法二:
思路:
1、先初始化 每人获得最低红包,保证了每人最低能获得0.01元
2、把总金额 减去 每人获得的金额后 剩余金额进行循环
3、把剩余金额循环,每次在 取剩余金额内的随机数作为红包的奖励,然后随机抽取一个用户作为中间人数,把红包金额 追加到 该用户的红包上。
4、直到剩余金额为0 ,停止循环
/**
* 发红包
* 10元发给5个用户,随机获取金额(最低0.01元)
* @param float $money 红包总金额
* @param int $people_num 用户人数
*/
function sendRedPackets(float $money , int $people_num){
// 最低红包金额
$min = 0.01;
if($money < $people_num * $min){
// 不够钱没人不足获得 0.01元
return false;
}
// 初始化用户获得的红包,每人获得0.01元
$user_arr = array_fill(0 , $people_num ,$min);
// 初始化没人获取0.01元
$money -= round($people_num * $min , 2);
while ($money >= $min) {
//获取每次分分配的金额
$one_money = mt_rand($min * 100 , $money * 100) / 100 ;
// 寻找每次获得的用户
$one_user = mt_rand(0 , $people_num - 1);
// 给抽中的用户加钱
$user_arr[$one_user] += $one_money;
// 扣减这部分金额
$money = round($money - $one_money , 2);
}
return $user_arr;
}
输出
// 给 5个人发红包 10元
$res = sendRedPackets(10 , 5);
echo '<pre />';
var_dump($res);
// array(5) {
// [0]=>
// float(0.33)
// [1]=>
// float(4.82)
// [2]=>
// float(0.74)
// [3]=>
// float(2.4)
// [4]=>
// float(1.71)
// }