博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
随机生成红包算法
阅读量:5024 次
发布时间:2019-06-12

本文共 5966 字,大约阅读时间需要 19 分钟。

random_red($total, $num, $max, $min); $time_end = microtime_float(); $time[] = $time_end - $time_start;}//echo array_sum($time)/5;function microtime_float(){ list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec);}//检查结果$reward_arr = $create_reward->random_red($total, $num, $max, $min);sort($reward_arr);//正序,最小的在前面$sum = 0;$min_count = 0;$max_count = 0;foreach($reward_arr as $i => $val) { if ($i<3) { echo "
第".($i+1)."个红包,金额为:".$val."
"; } if ($val == $max) { $max_count++; } if ($val < $min) { $min_count++; } $val = $val*100; $sum += $val;}echo "
";var_dump($reward_arr);//检测钱是否全部发完echo '

已生成红包总金额为:'.($sum/100).';总个数为:'.count($reward_arr).'

';//检测有没有小于0的值echo "
最大值:".($val/100).',共有'.$max_count.'个最大值,共有'.$min_count.'个值比最小值小';//正态分布图//对红包进行排序一下以显示正态分布特性$reward_arr = $create_reward->random_red($total, $num, $max, $min);$show = array();rsort($reward_arr);foreach($reward_arr as $k=>$value){ $t=$k%2; if(!$t) $show[]=$value; else array_unshift($show,$value);}//echo "
";var_dump($show);die;echo "设定最大值为:".$max.',最小值为:'.$min.'

';echo "
";foreach($show as $val){ #线条长度计算 $width=intval($num*$val*300/$total); echo "
";}echo "
红包金额 图示
 {
$val} 

";

 

引入文件Reward.php

rewardMoney = $rewardMoney * 100 - $rewardNum * $min; $this->rewardNum = $rewardNum; #计算出发出红包的平均概率值、精确到小数4位。 $avgRand = 1 / $this->rewardNum; $randArr = array(); #定义生成的数据总合sum $sum = 0; $t_count = 0; while ($t_count < $rewardNum) { #随机产出四个区间的额度 $c = rand(1, 100); if ($c < 15) { $t = round(sqrt(mt_rand(1, 1500))); } else if ($c < 65) { $t = round(sqrt(mt_rand(1500, 6500))); } else if ($c < 95) { $t = round(sqrt(mt_rand(6500, 9500))); } else { $t = round(sqrt(mt_rand(9500, 10000))); } ++$t_count; $sum += $t; $randArr[] = $t; } #计算当前生成的随机数的平均值,保留4位小数 $randAll = round($sum / $rewardNum, 4); #为将生成的随机数的平均值变成我们要的1/N,计算一下每个随机数要除以的总基数mixrand。此处可以约等处理,产生的误差后边会找齐 #总基数 = 均值/平均概率 $mixrand = round($randAll / $avgRand, 4); #对每一个随机数进行处理,并乘以总金额数来得出这个红包的金额。 $rewardArr = array(); foreach ($randArr as $key => $randVal) { #单个红包所占比例randVal $randVal = round($randVal / $mixrand, 4); #算出单个红包金额 $single = floor($this->rewardMoney * $randVal); #小于最小值直接给最小值 if ($single < $min) { $single += $min; } #大于最大值直接给最大值 if ($single > $max) { $single = $max; } #将红包放入结果数组 $rewardArr[] = $single; } #对比红包总数的差异、将差值放在第一个红包上 $rewardAll = array_sum($rewardArr); $rewardArr[0] = $rewardMoney * 100 - ($rewardAll - $rewardArr[0]);#此处应使用真正的总金额rewardMoney,$rewardArr[0]可能小于0 #第一个红包小于0时,做修正 if ($rewardArr[0] < 0) { rsort($rewardArr); $this->add($rewardArr, $min); } rsort($rewardArr); #随机生成的最大值大于指定最大值 if ($rewardArr[0] > $max) { #差额 $diff = 0; foreach ($rewardArr as $k => &$v) { if ($v > $max) { $diff += $v - $max; $v = $max; } else { break; } } $transfer = round($diff / ($this->rewardNum - $k + 1)); $this->diff($diff, $rewardArr, $max, $min, $transfer, $k); } return $rewardArr; } #处理所有超过最大值的红包 public function diff($diff, &$rewardArr, $max, $min, $transfer, $k) { #将多余的钱均摊给小于最大值的红包 for ($i = $k; $i < $this->rewardNum; $i++) { #造随机值 if ($transfer > $min * 20) { $aa = rand($min, $min * 20); if ($i % 2) { $transfer += $aa; } else { $transfer -= $aa; } } if ($rewardArr[$i] + $transfer > $max) continue; if ($diff - $transfer < 0) { $rewardArr[$i] += $diff; $diff = 0; break; } $rewardArr[$i] += $transfer; $diff -= $transfer; } if ($diff > 0) { $i++; $this->diff($diff, $rewardArr, $max, $min, $transfer, $k); } } #第一个红包小于0,从大红包上往下减 public function add(&$rewardArr, $min) { foreach ($rewardArr as &$re) { $dev = floor($re / $min); if ($dev > 2) { $transfer = $min * floor($dev / 2); $re -= $transfer; $rewardArr[$this->rewardNum - 1] += $transfer; } elseif ($dev == 2) { $re -= $min; $rewardArr[$this->rewardNum - 1] += $min; } else { break; } } if ($rewardArr[$this->rewardNum - 1] > $min || $rewardArr[$this->rewardNum - 1] == $min) { return; } else { $this->add($rewardArr, $min); } }}

引入文件CreateReward.php

splitReward($total, $num, $max - 0.01, $min); sort($result_merge); $result_merge[1] = $result_merge[1] + $result_merge[0]; $result_merge[0] = $max * 100; foreach ($result_merge as &$v) { $v = floor($v) / 100; } return $result_merge; }}

  运行结果

第1个红包,金额为:6.67

第2个红包,金额为:7.73
第3个红包,金额为:7.83

array(10) {  [0]=>  float(6.67)  [1]=>  float(7.73)  [2]=>  float(7.83)  [3]=>  float(8.46)  [4]=>  float(8.89)  [5]=>  float(9.21)  [6]=>  float(10.15)  [7]=>  float(10.48)  [8]=>  float(10.58)  [9]=>  float(20)}

已生成红包总金额为:100;总个数为:10

转载于:https://www.cnblogs.com/kevin-yang123/p/10044742.html

你可能感兴趣的文章
关于DataSet事务处理以及SqlDataAdapter四种用法
查看>>
bootstrap
查看>>
http://lorempixel.com/ 可以快速产生假图
查看>>
工程经验总结之吹水"管理大境界"
查看>>
为什么JS动态生成的input标签在后台有时候没法获取到
查看>>
20189210 移动开发平台第六周作业
查看>>
java之hibernate之基于外键的双向一对一关联映射
查看>>
rxjs一句话描述一个操作符(1)
查看>>
第一次独立上手多线程高并发的项目的心路历程
查看>>
ServiceStack 介绍
查看>>
Centos7下载和安装教程
查看>>
无谓的通宵加班之后的思索
查看>>
S1的小成果:MyKTV系统
查看>>
从setting文件导包
查看>>
编写一个函数isMerge,判断一个字符串str是否可以由其他两个字符串part1和part2“组合”而成...
查看>>
union和union all
查看>>
Github 开源:使用控制器操作 WinForm/WPF 控件( Sheng.Winform.Controls.Controller)
查看>>
PMD使用提醒
查看>>
Codeforces 887D Ratings and Reality Shows
查看>>
论文《A Generative Entity-Mention Model for Linking Entities with Knowledge Base》
查看>>