把一个数随机分成n份,随机数字和等于总数 PHP代码

把一个数随机分成n份,随机数字和等于总数 PHP代码

例如: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);

运行结果

<?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);

三、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)

转载自 https://www.fujieace.com/php/algorithm/rand-n.html

猜你喜欢

转载自blog.csdn.net/qq_42005284/article/details/88825223