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
)