There is known Random(0,1)
function, it is a uniformed random function, which means, it will give 0 or 1, with probability 50%. Implement Random(a, b)
that only makes calls to Random(0,1)
What I though so far is, put the range a-b in a 0 based array, then I have index 0, 1, 2...b-a.
then call the RANDOM(0,1)
b-a times, sum the results as generated idx. and return the element.
However since there is no answer in the book, I don't know if this way is correct or the best. How to prove that the probability of returning each element is exactly same and is 1/(b-a+1)
?
And what is the right/better way to do this?
If you have a RNG that returns
{0, 1}
with equal probability, you can easily create a RNG that returns numbers{0, 2^n}
with equal probability.To do this you just use your original RNG
n
times and get a binary number like0010110111
. Each of the numbers are (from 0 to 2^n) are equally likely.Now it is easy to get a RNG from
a
tob
, whereb - a = 2^n
. You just create a previous RNG and adda
to it.Now the last question is what should you do if
b-a
is not2^n
?Good thing that you have to do almost nothing. Relying on rejection sampling technique. It tells you that if you have a big set and have a RNG over that set and need to select an element from a subset of this set, you can just keep selecting an element from a bigger set and discarding them till they exist in your subset.
So all you do, is find
b-a
and find the first n such thatb-a <= 2^n
. Then using rejection sampling till you picked an element smallerb-a
. Than you just adda
.Divide and conquer could help us in generating a random number in range [a,b] using random(0,1). The idea is
The working 'C' code is as follows.
If your RANDOM(0, 1) returns either 0 or 1, each with probability 0.5 then you can generate bits until you have enough to represent the number (b-a+1) in binary. This gives you a random number in a slightly too large range: you can test and repeat if it fails. Something like this (in Python).
Your inclination to put the range from
0
toa-b
first is correct. However, you cannot do it as you stated. This question asks exactly how to do that, and the answer utilizes unique factorization. Writem=a-b
in base2
, keeping track of the largest needed exponent, saye
. Then, find the biggest multiple ofm
that is smaller than2^e
, call itk
. Finally, generatee
numbers withRANDOM(0,1)
, take them as the base2
expansion of some numberx
, ifx < k*m
, returnx
, otherwise try again. The program looks something like this (simple case when m<2^2):Now you can simply add
a
to the result to get uniformly distributed numbers betweena
andb
.When you sum random numbers, the result is not longer evenly distributed - it looks like a Gaussian function. Look up "law of large numbers" or read any probability book / article. Just like flipping coins 100 times is highly highly unlikely to give 100 heads. It's likely to give close to 50 heads and 50 tails.