需求:
5000元,随机分给10000人,要求每个人最少0.01,最大50;
分析:
5000元分给10000人,平均每人0.5,如果随机0.01-50,那么平均值就在25左右,这就有问题了
分化为两种结果:
1,在保证剩余人至少能分到0.01的情况下,按照0.01-50进行随机分配,这种会每个金额都有,但是绝大部分会只有0.01,结果统计如下:
范围 | 概率 |
---|---|
0.01 | 98.02% |
(0.01,5] | 0.209% |
(5-10] | 0.182% |
(10-15] | 0.212% |
(15-20] | 0.210% |
(20-25] | 0.187% |
(25-30] | 0.207% |
(30-35] | 0.194% |
(35-40] | 0.203% |
(40-45] | 0.183% |
(55-50] | 0.193% |
代码如下:
$total=50000;
$num=100000;
$max=50;
$min=0.01;
$rs=red_packet($total,$num,$max,$min);
shuffle($rs);
function red_packet($total,$num,$max,$min){
$re=[];
while ($num>0){
$num--;
$tmp_max=min($max,round($total-$num*$min,2));//保证剩下红包金额不小于范围中的最小值
$tmp_min=max($min,round($total-$num*$max,2));//保证剩下红包金额不大于范围中的最大值
$money=mt_rand($tmp_min*100,$tmp_max*100)/100;
$total-=$money;
$re[]=$money;
}
return $re;
}
这个函数返回的数组最好使用shuffle函数打散后再使用
2,使平均值始终保持在0.5左右,这样数据会比较平稳,金额都相差不大,获得大金额的概率非常低,统计结果如下:
范围 | 概率 |
---|---|
0.01 | 1.11% |
(0.01,0.2] | 19.54% |
(0.2-0.4] | 19.98% |
(0.4-0.6] | 20.10% |
(0.6-0.8] | 19.75% |
(0.8-1] | 19.45% |
(1,1.2] | 0.07% |
(1.2-50] | 0% |
代码如下:
$total=5000;
$num=10000;
$max=50;
$min=0.01;
$rs=red_packet($total,$num,$max,$min);
function red_packet($total,$num,$max,$min){
$re=[];
while ($num>0){
$vag=round($total/$num,2);
$num--;
$tmp_max=min($max,round($total-$num*$min,2));//保证剩下红包金额不小于范围中的最小值
$tmp_min=max($min,round($total-$num*$max,2));//保证剩下红包金额不大于范围中的最大值
$vag_diff=min($tmp_max-$vag,$vag-$tmp_min);//这是波动幅度
$end_max=$vag+$vag_diff;
$end_min=$vag-$vag_diff;
$money=mt_rand($end_min*100,$end_max*100)/100;
$total-=$money;
$re[]=$money;
}
return $re;
}
以上两种都不符合正态分布,第一种是大部分0.01,小部分在0.01-50之间均匀分布,第二种是大部分在0.01-1之间均匀分布,感觉要想正态分布,首要条件就是范围的中间值正好等于总的平均值,但结果也只会是均匀分布,就是获得每个金额的频率是相等的,想像不出正态分布应该是什么样的结果。
网友评论