How to Make 5 Random Numbers with Sum of 100

How to make 5 random numbers with sum of 100

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)
}

generate random integers with a specific sum

Create your first random number. After that you take the difference between the value of num1 and 100 as the max def of rnd. But to guarantee that their sum is 100, you have to check at the last num if the sum of all nums is 100. If not the value of your last num is the difference that their sum and 100.

And to simply your code and get a clean strcuture, put that code in a loop and instead of single numbers work with an int[5] array.


private int[] CreateRandomNumbersWithSum()
{
int[] nums = new int[5];
int difference = 100;
Random rnd = new Random();

for (int i = 0; i < nums.Length; i++)
{
nums[i] = rnd.Next(0, difference);

difference -= nums[i];
}

int sum = 0;

foreach (var num in nums)
sum += num;

if (sum != 100)
{
nums[4] = 100 - sum;
}

return nums;
}

Python: generate 5 random int (every has own range) with fixed sum

I'd start with the smallest ranges first, then pick the last one not randomly but as the difference between the sum of the other 4 and 100. Since random numbers can't be guaranteed to meet all the constraints, you may need to keep picking until you get a satisfactory answer.

def sum_to_100(range_list):
if sum(lo for lo,hi in range_list) > 100 or sum(hi for lo,hi in range_list) < 100:
raise ValueError('Solution is impossible within the constraints')
ordered_ranges = sorted((lo,hi,i) for i,(lo,hi) in enumerate(range_list))
n = len(range_list)
solution = []
while len(solution) != n or sum(solution) != 100:
index = len(solution)
lo, hi, i = ordered_ranges[index]
if index == n - 1:
final = 100 - sum(solution)
if lo <= final <= hi:
solution.append(final)
else: # start over
solution = []
else:
solution.append(random.randint(lo, hi))
# restore the original order
solution = [num for i,num in sorted(enumerate(solution), key=lambda x:ordered_ranges[x[0]][2])]
return solution

>>> sum_to_100([(40, 70), (0, 4), (0, 2), (22, 44), (0, 7)])
[59, 3, 1, 32, 5]
>>> sum_to_100([(40, 70), (0, 4), (0, 2), (22, 44), (0, 7)])
[47, 2, 0, 44, 7]

Generating a list of random numbers, summing to 1

The simplest solution is indeed to take N random values and divide by the sum.

A more generic solution is to use the Dirichlet distribution
which is available in numpy.

By changing the parameters of the distribution you can change the "randomness" of individual numbers

>>> import numpy as np, numpy.random
>>> print np.random.dirichlet(np.ones(10),size=1)
[[ 0.01779975 0.14165316 0.01029262 0.168136 0.03061161 0.09046587
0.19987289 0.13398581 0.03119906 0.17598322]]

>>> print np.random.dirichlet(np.ones(10)/1000.,size=1)
[[ 2.63435230e-115 4.31961290e-209 1.41369771e-212 1.42417285e-188
0.00000000e+000 5.79841280e-143 0.00000000e+000 9.85329725e-005
9.99901467e-001 8.37460207e-246]]

>>> print np.random.dirichlet(np.ones(10)*1000.,size=1)
[[ 0.09967689 0.10151585 0.10077575 0.09875282 0.09935606 0.10093678
0.09517132 0.09891358 0.10206595 0.10283501]]

Depending on the main parameter the Dirichlet distribution will either give vectors where all the values are close to 1./N where N is the length of the vector, or give vectors where most of the values of the vectors will be ~0 , and there will be a single 1, or give something in between those possibilities.

EDIT (5 years after the original answer): Another useful fact about the Dirichlet distribution is that you naturally get it, if you generate a Gamma-distributed set of random variables and then divide them by their sum.

Draw n random integers whose sum is equal to 100

Using only integer numbers and Fisher-Yates shuffle:

program cont3;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
const
SummandsCount = 5;
WantedSum = 100;
var
i, j, t, Cnt, WhereToInsert: integer;
JustNaturalNumbers: array[1..WantedSum] of Integer;
DividingPoints: array[0..SummandsCount] of Integer;
begin
Randomize;
Cnt := 1;
DividingPoints[0] := 0;
DividingPoints[SummandsCount] := 100;
for i := 1 to WantedSum - 1 do
JustNaturalNumbers[i] := i;
for i := WantedSum - 1 downto WantedSum - SummandsCount + 1 do begin
j := 1 + Random(i);
WhereToInsert := Cnt;
while (WhereToInsert > 1) and (JustNaturalNumbers[j] < DividingPoints[WhereToInsert-1]) do begin
Dec(WhereToInsert);
DividingPoints[WhereToInsert + 1] := DividingPoints[WhereToInsert]
end;
DividingPoints[WhereToInsert] := JustNaturalNumbers[j];
JustNaturalNumbers[j] := JustNaturalNumbers[i];
Inc(Cnt);
end;
t := 0;
for i := 1 to SummandsCount do begin
Writeln(DividingPoints[i] - DividingPoints[i-1]);
t := t + (DividingPoints[i] - DividingPoints[i-1]);
end;
Writeln('Sum = ', t);
Readln;
end.

Output example:

22
4
7
18
49
Sum = 100

How to generate random numbers summing up to 100?

You can generate four random numbers, for example in range 0..100, then rescale them to have 100 as sum:

x_i' = 1 + x_i*96.0/sum

This solution does not provide uniform distribution of {x_i}.

@PeterWood found better answer for this question Random numbers that add to 100: Matlab

Javascript generate 5 random numbers whose sum is equal to 100

let sum = 100
const numbers = []
for (let i = 0; i < 4; i++) {
const randomNumber = Math.floor(Math.random() * sum)
sum -= randomNumber < 0 ? 0 : randomNumber
numbers.push(randomNumber < 0 ? 0 : randomNumber)
}
numbers.push(sum)
console.log(numbers, numbers.reduce((a, b) => a + b, 0)) // 5 random numbers of sum 100

Producing random numbers, which if added equal to a specified number

You can generate your first random number between 1 and (100-3). Suppose your first random number is X. The next random number you generate should be between X and (100-2). Suppose that number is Y. The next random number should be between (X+Y) and (100-1). Suppose that number is Z.

Now you have your fourth random number which is 100-X-Y-Z. Double check a few of these to show that it has the same distribution as your current number generator to check your work.



Related Topics



Leave a reply



Submit