How to make 5 random numbers with sum of 100 [duplicate]

do you know a way to split an integer into say... 5 groups. Each group total must be at random but the total of them must equal a fixed number.

for example I have "100" I wanna split this number into

1- 20
2- 3
3- 34
4- 15
5- 18

EDIT: i forgot to say that yes a balance would be a good thing.I suppose this could be done by making a if statement blocking any number above 30 instance.


Solution 1:

I have a slightly different approach to some of the answers here. I create a loose percentage based on the number of items you want to sum, and then plus or minus 10% on a random basis.

I then do this n-1 times (n is total of iterations), so you have a remainder. The remainder is then the last number, which isn't itself truley random, but it's based off other random numbers.

Works pretty well.

/**
 * Calculate n random numbers that sum y.
 * Function calculates a percentage based on the number
 * required, gives a random number around that number, then
 * deducts the rest from the total for the final number.
 * Final number cannot be truely random, as it's a fixed total,
 * but it will appear random, as it's based on other random
 * values.
 * 
 * @author Mike Griffiths
 * @return Array
 */
private function _random_numbers_sum($num_numbers=3, $total=500)
{
    $numbers = [];

    $loose_pcc = $total / $num_numbers;

    for($i = 1; $i < $num_numbers; $i++) {
        // Random number +/- 10%
        $ten_pcc = $loose_pcc * 0.1;
        $rand_num = mt_rand( ($loose_pcc - $ten_pcc), ($loose_pcc + $ten_pcc) );

        $numbers[] = $rand_num;
    }

    // $numbers now contains 1 less number than it should do, sum 
    // all the numbers and use the difference as final number.
    $numbers_total = array_sum($numbers);

    $numbers[] = $total - $numbers_total;

    return $numbers;
}

This:

$random = $this->_random_numbers_sum();
echo 'Total: '. array_sum($random) ."\n";
print_r($random);

Outputs:

Total: 500
Array
(
    [0] => 167
    [1] => 164
    [2] => 169
)

Solution 2:

Pick 4 random numbers, each around an average of 20 (with distribution of e.g. around 40% of 20, i.e. 8). Add a fifth number such that the total is 100.

In response to several other answers here, in fact the last number cannot be random, because the sum is fixed. As an explanation, in below image, there are only 4 points (smaller ticks) that can be randomly choosen, represented accumulatively with each adding a random number around the mean of all (total/n, 20) to have a sum of 100. The result is 5 spacings, representing the 5 random numbers you are looking for.

only 4 random point between 0 and 100

Solution 3:

Depending on how random you need it to be and how resource rich is the environment you plan to run the script, you might try the following approach.

<?php
set_time_limit(10);

$number_of_groups   = 5;
$sum_to             = 100;

$groups             = array();
$group              = 0;

while(array_sum($groups) != $sum_to)
{
    $groups[$group] = mt_rand(0, $sum_to/mt_rand(1,5));

    if(++$group == $number_of_groups)
    {
        $group  = 0;
    }
}

The example of generated result, will look something like this. Pretty random.

[root@server ~]# php /var/www/dev/test.php
array(5) {
  [0]=>
  int(11)
  [1]=>
  int(2)
  [2]=>
  int(13)
  [3]=>
  int(9)
  [4]=>
  int(65)
}
[root@server ~]# php /var/www/dev/test.php
array(5) {
  [0]=>
  int(9)
  [1]=>
  int(29)
  [2]=>
  int(21)
  [3]=>
  int(27)
  [4]=>
  int(14)
}
[root@server ~]# php /var/www/dev/test.php
array(5) {
  [0]=>
  int(18)
  [1]=>
  int(26)
  [2]=>
  int(2)
  [3]=>
  int(5)
  [4]=>
  int(49)
}
[root@server ~]# php /var/www/dev/test.php
array(5) {
  [0]=>
  int(20)
  [1]=>
  int(25)
  [2]=>
  int(27)
  [3]=>
  int(26)
  [4]=>
  int(2)
}
[root@server ~]# php /var/www/dev/test.php
array(5) {
  [0]=>
  int(9)
  [1]=>
  int(18)
  [2]=>
  int(56)
  [3]=>
  int(12)
  [4]=>
  int(5)
}
[root@server ~]# php /var/www/dev/test.php
array(5) {
  [0]=>
  int(0)
  [1]=>
  int(50)
  [2]=>
  int(25)
  [3]=>
  int(17)
  [4]=>
  int(8)
}
[root@server ~]# php /var/www/dev/test.php
array(5) {
  [0]=>
  int(17)
  [1]=>
  int(43)
  [2]=>
  int(20)
  [3]=>
  int(3)
  [4]=>
  int(17)
}