3

Possible Duplicate:
Getting N random numbers that the sum is M

Hi I have a question that:

how can i get random values where the sum of all of them is 1. like {0.5,0.5} or {0.25,0.25,0.5} and more. also the number of these values are different every time ,once can be 2 and once can be 3 like the example above! thanks.

Community
  • 1
  • 1
user472221
  • 3,014
  • 11
  • 35
  • 42
  • 3
    If they must add up to something, they're not exactly random. – cdhowie Dec 10 '10 at 06:52
  • for example I have an array which has 10000 elements in it and each element has its own probability (Element is an object that has two fields 1)digit2)probability) and the sum of all probability must be 1! So how can i do this with out random? – user472221 Dec 10 '10 at 06:57
  • 2
    Generate random numbers (between 0 and array.length) and increment the element at the number generated. Do this `n` times. Afterwards, divide all elements by `n` and you have the probability (which will sum to 1) of the elements. – Reese Moore Dec 10 '10 at 07:00
  • 1
    Duplicate: http://stackoverflow.com/questions/2640053/getting-n-random-numbers-that-the-sum-is-m/2640067#2640067 – Guillaume Dec 10 '10 at 07:09
  • @cdhowie: Why? You take an interval (between 0 and the intended sum) and randomly place points in that interval. Show me where that is obviously non-random. – Joey Dec 12 '10 at 19:45

5 Answers5

12

I'll outline the basic algorithm for you:

  • decide how many random numbers you will generate that will be summed.

  • generate that many random numbers.

  • decide what they should all add up to.

  • divide number from the previous step by the sum of the random numbers.

  • divide each random number by the number from the previous step.

Basically what you'll be doing is generating a bunch of unbounded random numbers and then adjusting them all so they all add up to some specific number.

BTW: In the very unlikely event that all the random numbers you generate are zero, you'll have a divide by zero error with this algorithm. So you should trap for that in your implementation and retry the random number generation in a loop until you get a non-zero sum of random numbers.

Asaph
  • 159,146
  • 25
  • 197
  • 199
  • 2
    +1 - Though it should be noted that fp rounding errors might mean that the numbers don't exactly sum to 1.0. – Stephen C Dec 10 '10 at 07:16
  • @Stephen C: Good point. Hopefully the floating point rounding errors don't impact the behavior of the program in a significant way. – Asaph Dec 10 '10 at 07:21
1

In general you can generate an array of random size:

    java.util.Random rand = new java.util.Random();
    final int MAX_SIZE = 100;
    double[] a = new double[1 + rand.nextInt(MAX_SIZE)];

(Here I'm assuming you will not want arrays larger than 100 elements.)

Then you fill the array with random positive numbers:

    for (int i = 0; i < a.length; ++ i)
    {
        a[i] = rand.nextDouble();
    }

Then you normalize the array (divide each element by the total sum). First we compute the total sum:

    double sum = 0.0;
    for (int i = 0; i < a.length; ++ i)
    {
        sum += a[i];
    }

Then divide each array element by the sum:

    for (int i = 0; i < a.length; ++ i)
    {
        a[i] /= sum; 
    }

If you want shorter code, you can combine the loop that accumulates the sum with the loop that fills the array with random positive integers. Here is the resulting code:

    java.util.Random rand = new java.util.Random();
    final int MAX_SIZE = 100;
    double[] a = new double[1 + rand.nextInt(MAX_SIZE)];

    double sum = 0.0;
    for (int i = 0; i < a.length; ++ i)
    {
        a[i] = rand.nextDouble();
        sum += a[i];
    }

    for (int i = 0; i < a.length; ++ i)
    {
        a[i] /= sum; 
    }
dsg
  • 12,924
  • 21
  • 67
  • 111
0

Well, I think that the easiest way would be something like this:

To generate two numbers:

r1 = new RandomNumber
r2 = 1 - r1

TO generate three numbers:

r1 = new RandomNumber
r2 = r1 / 2
r3 = 1 - r1
r1 = r1 / 2

I do not know if there is any simpler way of doing this though and the code above is just pseudo code.

npinti
  • 51,780
  • 5
  • 72
  • 96
0

Like @dsg but shorter. It allows you to specify what the sum should be.

public static double[] randomDoubles(int size, double sum) {
    double total=0, doubles[]=new double[size];
    for(int i=0;i<size;i++) total += doubles[i] = Math.random();
    for(int i=0;i<size;i++) doubles[i] *= sum/total;
    return doubles;
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

How about for n random numbers:

r1 = random(0,1)
r2 = random(0, 1-r1)
r3 = random(0, 1-r1-r2)
...
r(n) = 1 - r1-r2-f3...-r(n-1)
Fakrudeen
  • 5,778
  • 7
  • 44
  • 70