2020-01-08 19:32:01
围观(4439)
微信红包有个好玩的地方,比如可以将 10 元放入红包,设置红包数量为 10 个.然后系统会自动将这 10 元拆分,有的人可能领到了几块钱,而有的人就只领到了几分钱.
实现方法:
function getRedPacket($price, $total = 10) { $min_price = 0.01; $temp = []; $return = []; for ($i = 1; $i < $total; ++$i) { // 红包金额的最大值 $max_total = ($price - ($total - $i) * $min_price) / ($total - $i); if ($max_total < 0) break; // 随机产生一个红包金额 $money = @mt_rand($min_price * 100, $max_total * 100) / 100; // 剩余红包总额 $price = $price - $money; // 保留两位有效数字 $temp[$i] = round($money, 2); } $temp[$i] = round($price, 2); $return['money'] = $temp; $return['total'] = array_sum($temp); return $return; }
调用该方法,可以得到这样的数据(实际返回的是数组 json 格式需要自己转):
{ "money": { "1": 1.06, "2": 0.01, "3": 0.45, "4": 1.28, "5": 0.91, "6": 0.7, "7": 1.79, "8": 1.87, "9": 1, "10": 0.93 }, "total": 10 }
其实实现方法不难,重点是代码中的这句:
$max_total = ($price - ($total - $i) * $min_price) / ($total - $i);
十个十元的红包,循环九次执行这个算法之后,得到的结果是:
(10 - (10 - 1) *0.01) / (10 - 1) 得出结果 1.1011111111111 (9.45 - (10 - 2) *0.01) / (10 - 2) 得出结果 1.17125 (9.3 - (10 - 3) *0.01) / (10 - 3) 得出结果 1.3185714285714 (9.06 - (10 - 4) *0.01) / (10 - 4) 得出结果 1.5 (7.72 - (10 - 5) *0.01) / (10 - 5) 得出结果 1.534 (6.91 - (10 - 6) *0.01) / (10 - 6) 得出结果 1.7175 (6.62 - (10 - 7) *0.01) / (10 - 7) 得出结果 2.1966666666667 (6.29 - (10 - 8) *0.01) / (10 - 8) 得出结果 3.135 (5.45 - (10 - 9) *0.01) / (10 - 9) 得出结果 5.44
可以看出,该算法就是: ( 剩余的金额 - ( 总金额 - 次数 ) * 0.01 ) / ( 总金额 - 次数 )
第一次循环时,剩余的金额是 10 因为总金额就 10 ,然后经过计算得出的结果是 1.1011111111111 如果传的是 10 元 分成 10 个,那么第一次的结果总是一致的.
拿到了第一个结果,就可以根据最低金额(0.01 一分钱),和刚才计算出来的金额,进行生成随机数.
比如生成一个随机数是 0.53 ,就将这个数存入数组,因为这个数就是第一个红包的金额了,存的时候注意下保留两位小数.
说一下,这里将最低金额 0.01 和 最大金额(算法算出的金额) 进行乘 100 计算, 算完再除 100 ,原因是为了对 "分" 做到更加精确,比如写 微信/支付宝/银联 的支付开发,支付金额都是用单位为分的金额传输的.
得到了第一个红包的金额,就可以将总金额 减 刚才得到的随机数(第一个红包),就得到了目前的剩余总金额,然后一直还需要循环八次,重复执行得到九个红包的金额.
可能有人会问,还有最后一个红包金额呢? 其实很简单,你都得到了九个红包了,并且每次执行代码都会得到一个 "目前的红包总额", 那第十个红包不就是这个总额了...
所以,根据上面的代码可以拆分红包,但是... 基本上最后一个红包是最大的,比如拆分三次的结果:
{ "money": { "1": 0.73, "2": 0.6, "3": 0.89, "4": 0.47, "5": 0.65, "6": 0.2, "7": 0.37, "8": 0.94, "9": 1.76, "10": 3.39 }, "total": 10 }
{ "money": { "1": 0.53, "2": 1.09, "3": 0.61, "4": 0.42, "5": 0.8, "6": 0.99, "7": 0.06, "8": 2.44, "9": 0.84, "10": 2.22 }, "total": 10 }
{ "money": { "1": 0.22, "2": 0.16, "3": 0.86, "4": 1.28, "5": 0.58, "6": 1.52, "7": 1.13, "8": 1.62, "9": 0.76, "10": 1.87 }, "total": 10 }
博主并没有特意把第十个红包最大的数据拿出来说,而是三次执行代码,拿到的数据就是这样的.
都是第十个(最后一个)红包的金额最大,如果介意,可以使用这个函数把数组值打乱:
shuffle(array &array);
比如这样调用:
$data = getRedPacket(10, 10); // 以下数据没有打乱 基本上第十个红包是最大的 echo json_encode($data); // 进行打乱数据 shuffle($data['money']); // 再次输出的数据 和第一次输出的数据顺序就不一样了 echo json_encode($data);
本文地址 : bubaijun.com/page.php?id=161
版权声明 : 未经允许禁止转载!
上一篇文章: Windows使用Laravel任务调度
下一篇文章: ThinkPHP框架使用支付宝SDK并发起支付