例如:100随机分成5份,5个数字的和等于100;
一、100个数随机分成10份:
说明:
1、此算法$money_total值可大于 $personal_num 也可以小于$personal_num;
2、得出来的结果是保留两位小数点;
3、相加和等于100;可用于发红包,精准到小数;
4、值类型结果是string(字符串);
$money_total=100;
$personal_num=10;
$min_money=0.01;
$money_right=$money_total;
$randMoney=[];
for($i=1;$i<=$personal_num;$i++){
if($i== $personal_num){
$money=$money_right;
}else{
$max=$money_right*100 - ($personal_num - $i ) * $min_money *100;
$money= rand($min_money*100,$max) /100;
$money=sprintf("%.2f",$money);
}
$randMoney[]=$money;
$money_right=$money_right - $money;
$money_right=sprintf("%.2f",$money_right);
}
shuffle($randMoney);
var_dump($randMoney);
运行结果:
- array (size=10)
- 0 => string '54.91' (length=5)
- 1 => string '3.02' (length=4)
- 2 => string '4.59' (length=4)
- 3 => string '12.76' (length=5)
- 4 => string '0.02' (length=4)
- 5 => string '22.83' (length=5)
- 6 => string '0.01' (length=4)
- 7 => string '0.01' (length=4)
- 8 => string '0.01' (length=4)
- 9 => string '1.84' (length=4)
二、100随机分成5份:
说明:
1、此算法$total_money值必须大于$total_num;
2、得出来的结果是整数;
3、相加和等于100;
4、值类型结果是int(整型);
<?php
$total_money=100;
$total_num=5;
$total_money=$total_money - $total_num;
for($i=$total_num;$i>0;$i--){
$data[$i]=1;
$ls_money=0;
if($total_money>0){
if($i==1){
$data[$i] +=$total_money;
}else{
$max_money=floor($total_money/$i);
$ls_money=mt_rand(0,$max_money);
$data[$i]+=$ls_money;
}
}
$total_money -= $ls_money;
}
var_dump($data);
运算结果:
- array (size=5)
- 5 => int 5
- 4 => int 17
- 3 => int 23
- 2 => int 9
- 1 => int 46
三、6人随机分成3组
<?php
$div=3; //分成几组
$total=6; //总数
$a=range(0,$div-1);
$base=($total-array_sum($a))/$div;
for($len=count($a),$i=0; $i<$len; $i++){
$a[$i]+=$base;
}
shuffle($a); //打乱排序
var_dump($a);//$a中便是分的不等数
运行结果:
- array (size=3)
- 0 => int 2
- 1 => int 3
- 2 => int 1
四、100随机分成9份
此php算法有点特殊,它的结果可以是int整型,也可以是float浮点型;我们再看另一种写法:当我们把100这个数随机分成9份的时候,结果就不一样喽,如下:
<?php
$div=9;
$total=100;
$a=range(0,$div-1);
$base=($total-array_sum($a))/$div;
for($len=count($a),$i=0; $i<$len; $i++){
$a[$i]+=$base;
}
shuffle($a); //打乱排序
var_dump($a);//$a中便是分的不等数
运行结果:
- array (size=9)
- 0 => float 14.111111111111
- 1 => float 12.111111111111
- 2 => float 13.111111111111
- 3 => float 8.1111111111111
- 4 => float 11.111111111111
- 5 => float 10.111111111111
- 6 => float 15.111111111111
- 7 => float 9.1111111111111
- 8 => float 7.1111111111111
从上面结果我们可以看,当不能整除的时候,得出来的结果不是整型,而且,得出来的结果相加它的值是不等于100的,只会无限的接近100;不信的话你可以把上面9个值相加,它的结果一定会小于100;
具体你想实现什么样的效果?请根据你的场景来采用不同的算法;
以下是来自网友的算法,经过我的整理发到此文章中来,欢迎大家点评!
五、100随机分成9份
我也自己写了一个,但是没有大家写得好,希望大家不要笑,我写的这个算法呢,结果都是浮点型float,而且相加的和也是小于100,但是它接近不了100,经常相加的和等于99;这就很尴尬了!
<?php
$total = 100; //待划分的数字
$div = 9; //分成的份数
$area = 10; //各份数间允许的最大差值
$average = round($total / $div);
$sum = 0;
$result = array_fill( 1, $div, 0 );
for( $i = 1; $i < $div; $i++ ){
//根据已产生的随机数情况,调整新随机数范围,以保证各份间差值在指定范围内
if( $sum > 0 ){
$max = 0;
$min = 0 - round( $area / 2 );
}elseif( $sum < 0 ){
$min = 0;
$max = round( $area / 2 );
}else{
$max = round( $area / 2 );
$min = 0 - round( $area / 2 );
}
//产生各份的份额
$random = rand( $min, $max );
$sum += $random;
$result[$i] = $average + $random;
}
//最后一份的份额由前面的结果决定,以保证各份的总和为指定值
$result[$div] = $average - $sum;
//结果呈现
var_dump($result);
echo '总和:', array_sum( $result );
运行结果:
- array(9) {
- [1]=>
- float(11)
- [2]=>
- float(16)
- [3]=>
- float(10)
- [4]=>
- float(6)
- [5]=>
- float(15)
- [6]=>
- float(9)
- [7]=>
- float(11)
- [8]=>
- float(10)
- [9]=>
- float(11)
- }
- 总和:99
六、100随机分成5份
下面是我自己写的一个PHP算法,看看有没有大家需要的;得出来的结果都是整型,就算把100这个数随机分成9份,相加总和还会等于100;我示例代码是把100分成5份的。
<?php
//随机整型利用“不同”就有顺序的原理,
function randomDivInt($div,$total){
$remain=$total;
$max_sum=($div-1)*$div/2;
$p=$div; $min=0;
$a=array();
for($i=0; $i<$div-1; $i++){
$max=($remain-$max_sum)/($div-$i);
$e=rand($min,$max);
$min=$e+1; $max_sum-=--$p;
$remain-=$e;
$a[$e]=true;
}
$a=array_keys($a);
$a[]=$remain;
return $a;
}
for($i=0; $i<3; $i++){
$a=randomDivInt(5,100);
var_dump($a);//$a中便是分的不等数
var_dump(array_sum($a));
}
运行结果:
- array(5) {
- [0]=>
- int(0)
- [1]=>
- int(13)
- [2]=>
- int(15)
- [3]=>
- int(22)
- [4]=>
- int(50)
- }
- int(100)
- array(5) {
- [0]=>
- int(9)
- [1]=>
- int(13)
- [2]=>
- int(15)
- [3]=>
- int(27)
- [4]=>
- int(36)
- }
- int(100)
- array(5) {
- [0]=>
- int(13)
- [1]=>
- int(16)
- [2]=>
- int(22)
- [3]=>
- int(23)
- [4]=>
- int(26)
- }
- int(100)
2018年06月26日 00:20:04 沙发
这个应该也可以理解为:PHP从p个数字中选出m个数,使其和等于n 吧!
2018年06月26日 00:51:13 1层
@小桥流水 当然可以。
2017年08月11日 21:38:03 板凳
算法东西看不懂,也不想懂,太伤脑筋了。
2017年05月12日 19:17:36 地板
我也自己写了一个,(此文章第五个就是我写的,博主已经把它整理到文章去了!)但是没有大家写得好,希望大家不要笑,我写的这个算法呢,结果都是浮点型float,而且相加的和也是小于100,但是它接近不了100,经常相加的和等于99;这就很尴尬了!
2017年05月12日 19:23:29 1层
@PHP算法吹牛大师 其实你的代码也没什么问题,只能说结果会和博客文章中所讲的算法第三种一样,都会无限接近100;你之所以相加和经常等于99;那是因为你用了四舍五入函数:round();因此才会造成这样!
2017年05月12日 19:08:59 4楼
下面是我自己写的一个PHP算法(算法已经被博主整理到此文章去了,此文章第6个算法就是我写的。),看看有没有大家需要的;得出来的结果都是整型!
例如:把100这个数随机分成9份,相加总和还等于100;
运行结果如下: