6

I need a random number generator that picks numbers over a specified range with a programmable mean.

For example, I need to pick numbers between 2 and 14 and I need the average of the random numbers to be 5.

I use random number generators a lot. Usually I just need a uniform distribution.

I don't even know what to call this type of distribution.

Thank you for any assistance or insight you can provide.

fbrereto
  • 35,429
  • 19
  • 126
  • 178
  • 10
    Are you sure that you provided enough information about the distribution? I believe mean value is not enough. Consider this example: let's say we generate random numbers from `{0, 1, 2}` with 1 mean. Now take a look at these two generators: `Generator1 (0: 40%, 1: 20%, 2: 40%)`, `Generator2 (0:10%, 1: 80%, 2:10%)`. For both of them average result would be 1. – Grzegorz Oledzki Oct 07 '09 at 21:38
  • 1
    A near duplicate: http://stackoverflow.com/questions/977354/generating-non-uniform-random-numbers. And non-flat pseudo-random distributions are a standard topic that has been addressed more than once on SO. Give more information and we can point you in the right direction. – dmckee --- ex-moderator kitten Oct 07 '09 at 22:11
  • If the target distribution is not easily represented by a integrable PDF look at: http://stackoverflow.com/questions/423006/how-do-i-generate-points-that-match-a-histogram – dmckee --- ex-moderator kitten Oct 07 '09 at 22:26
  • WRT what GrzegorzOledzki says, you can meet the requirements as stated using uniform distribution except making 2 happen 14 times more often than the other values - ie uniform selection from a list with 14 repeats of the 2. Pretty easy, but not likely to be appropriate. –  Oct 07 '09 at 22:33

8 Answers8

6

You might be able to use a binomial distribution, if you're happy with the shape of that distribution. Set n=12 and p=0.25. This will give you a value between 0 and 12 with a mean of 3. Just add 2 to each result to get the range and mean you are looking for.

Edit: As for implementation, you can probably find a library for your chosen language that supports non-uniform distributions (I've written one myself for Java).

A binomial distribution can be approximated fairly easily using a uniform RNG. Simply perform n trials and record the number of successes. So if you have n=10 and p=0.5, it's just like flipping a coin 10 times in a row and counting the number of heads. For p=0.25 just generate uniformly-distributed values between 0 and 3 and only count zeros as successes.

If you want a more efficient implementation, there is a clever algorithm hidden away in the exercises of volume 2 of Knuth's The Art of Computer Programming.

Dan Dyer
  • 53,737
  • 19
  • 129
  • 165
  • the link to ["(I've written one myself for Java)."](https://uncommons-maths.dev.java.net/) is not available – yishaiz Oct 07 '14 at 20:09
3

You haven't said what distribution you are after. Regarding your specific example, a function which produced a uniform distribution between 2 and 8 would satisfy your requirements, strictly as you have written them :)

Hugh Allen
  • 6,509
  • 1
  • 34
  • 44
2

If you want a non-uniform distribution of the random number, then you might have to implement some sort of mapping, e.g:

// returns a number between 0..5 with a custom distribution
int MyCustomDistribution()
{
  int r = rand(100); // random number between 0..100
  if (r < 10) return 1;
  if (r < 30) return 2;
  if (r < 42) return 3;
  ...
}
M4N
  • 94,805
  • 45
  • 217
  • 260
2

Based on the Wikipedia sub-article about non-uniform generators, it would seem you want to apply the output of a uniform pseudorandom number generator to an area distribution that meets the desired mean.

fbrereto
  • 35,429
  • 19
  • 126
  • 178
1

You can create a non-uniform PRNG from a uniform one. This makes sense, as you can imagine taking a uniform PRNG that returns 0,1,2 and create a new, non-uniform PRNG by returning 0 for values 0,1 and 1 for the value 2.

There is more to it if you want specific characteristics on the distribution of your new, non-uniform PRNG. This is covered on the Wikipedia page on PRNGs, and the Ziggurat algorithm is specifically mentioned.

With those clues you should be able to search up some code.

csl
  • 10,937
  • 5
  • 57
  • 89
0

My first idea would be:

  • generate numbers in the range 0..1
  • scale to the range -9..9 ( x-0.5; x*18)
  • shift range by 5 -> -4 .. 14 (add 5)
  • truncate the range to 2..14 (discard numbers < 2)

that should give you numbers in the range you want.

Frank Bollack
  • 24,478
  • 5
  • 49
  • 58
  • 1
    But as you discard the numbers < 2 your average moves upward away from 5 doesn't it? –  Oct 07 '09 at 21:51
0

You need a distributed / weighted random number generator. Here's a reference to get you started.

Eric J.
  • 147,927
  • 63
  • 340
  • 553
0
Assign all numbers equal probabilities,

while currentAverage not equal to intendedAverage (whithin possible margin)

 pickedNumber = pick one of the possible numbers (at random, uniform probability, if you pick intendedAverage pick again)

 if (pickedNumber is greater than intendedAverage and currentAverage<intendedAverage) or (pickedNumber is less than intendedAverage and currentAverage>intendedAverage)

   increase pickedNumber's probability by delta at the expense of all others, conserving sum=100%

 else

   decrease pickedNumber's probability by delta to the benefit of all others, conserving sum=100%

 end if

 delta=0.98*delta (the rate of decrease of delta should probably be experimented with)

end while

Emilio M Bumachar
  • 2,532
  • 3
  • 26
  • 30