2

Possible Duplicate:
Generate random number with non-uniform density

I try to identify/create a function ( in Java ) that give me a nonuniform distributed sequence of number. if I has a function that say function f(x), and x>0 it will give me a random number from 0 to x.

The function most work with any given x and this below is only a example how I want to have.

But if we say x=100 the function f(x) will return s nonunifrom distributed.

And I want for example say

0 to 20 be approximately 20% of all case.

21 to 50 be approximately 50% of all case.

51 to 70 be approximately 20% of all case.

71 to 100be approximately 10 of all case.

In short somting that give me a number like normal distribution and it peek at 30-40 in this case x is 100.

http://en.wikipedia.org/wiki/Normal_distribution

( I can use a uniform random gen as score if need, and only a function that will transfrom the uniform result to a non-uniform result. )

EDIT

My final solution for this problem is:

/**
 * Return a value from [0,1] and mean as 0.3, It give 10% of it is lower
 * then 0.1. 5% is higher then 0.8 and 30% is in rang 0.25 to 0.45
 *
 * @return
 */
public double nextMyGaussian() {
    double d = -1000;
    while (d < -1.5) {
        // RANDOMis Java's normal Random() class.
        // The nextGaussian is normal give a value from -5 to +5?
        d = RANDOM.nextGaussian() * 1.5;
    }
    if (d > 3.5d) {
        return 1;
    }
    return ((d + 1.5) / 5);
}
Community
  • 1
  • 1
FIG-GHD742
  • 2,486
  • 1
  • 19
  • 27

5 Answers5

4

A simple solution would be to generate a first random number between 0 and 9.

0 means the 10 first percents, 1 the ten following percents, etc.

So if you get 0 or 1, you generate a second random number between 0 and 20. If you get 2, 3, 4, 5 or 6, you generate a second random number between 21 and 50, etc.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
2

Could you just write a function that sums a number of random numbers it the 1-X range and takes an average? this will tend to the normal distribution as n increases

See:

Generate random numbers following a normal distribution in C/C++

I hacked something like the below:

class CrudeDistribution {

    final int TRIALS = 20;

    public int getAverageFromDistribution(int upperLimit) {
        return getAverageOfRandomTrials(TRIALS, upperLimit);
    }

    private int getAverageOfRandomTrials(int trials, int upperLimit) {
        double d = 0.0;
        for (int i=0; i<trials; i++) {
            d +=getRandom(upperLimit);
        }
        return (int) (d /= trials);
    }

    private int getRandom(int upperLimit) {
        return (int) (Math.random()*upperLimit)+1;
    }
}

There are libraries in Commons-Math that can generate distributions based on means and standard deviations (that measure the spread). and in the link some algorithms that do this.

Probably a fun hour of so of hunting to find the relevant 2 liner:

https://commons.apache.org/math/userguide/distribution.html

Community
  • 1
  • 1
Alex
  • 670
  • 11
  • 21
  • there is Math.nextGaussian() but this uses a standard deviation and could generate an unlimitedly large number requiring bucketing. – Alex Nov 07 '12 at 23:18
  • Why is `CrudeDistribution` and `TRIALS` package scope? – Steve Kuo Nov 07 '12 at 23:27
  • I think this is the post that is most close to a good solution here. `Steve Kuo` Tt do not matter, is probably not a pure java code for that matter. – FIG-GHD742 Nov 08 '12 at 05:25
0

One solution would be to do a random number between 1-100 and based on the result do another random number in the appropriate range.

1-20 -> 0-20

21-70 -> 21-50

71-90 -> 51-70

91-100 -> 71-100

Hope that makes sense.

JustinKSU
  • 4,875
  • 2
  • 29
  • 51
  • It might make sense if you explain how it satisfies the requirements. It's not at all clear just from this. – Don Roby Nov 07 '12 at 22:59
0

You need to create the f(x) first.

Assuming values x are equiprobable, your f(x) is

double f(x){
if(x<=20){
 return x;
}else if (x>20 && x<=70){
 return (x-20)/50*30+20;
} else if(...

etc

thedayofcondor
  • 3,860
  • 1
  • 19
  • 28
0

Just generate a bunch, say at least 30, uniform random numbers between 0 and x. Then take the mean of those. The mean will, following the central limit theorem, be a random number from a normal distribution centered around x/2.

Mr Alpha
  • 1,813
  • 1
  • 16
  • 26