Question: Suppose you have a random number generator randn() that returns a uniformly distributed random number between 0 and n-1. Given any number m, write a random number generator that returns a uniformly distributed random number between 0 and m-1.
My answer:
-(int)randm() {
int k=1;
while (k*n < m) {
++k;
}
int x = 0;
for (int i=0; i<k; ++i) {
x += randn();
}
if (x < m) {
return x;
} else {
return randm();
}
}
Is this correct?
You’re close, but the problem with your answer is that there is more than one way to write a number as a sum of two other numbers.
If
m<n, then this works because the numbers0,1,...,m-1appear each with equal probability, and the algorithm terminates almost surely.This answer does not work in general because there is more than one way to write a number as a sum of two other numbers. For instance, there is only one way to get
0but there are many many ways to getm/2, so the probabilities will not be equal.Example:
n = 2andm=3so the probability distribution from your method is
which is not uniform.
To fix this, you can use unique factorization. Write
min basen, keeping track of the largest needed exponent, saye. Then, find the biggest multiple ofmthat is smaller thann^e, call itk. Finally, generateenumbers withrandn(), take them as the basenexpansion of some numberx, ifx < k*m, returnx, otherwise try again.Assuming that
m < n^2, then