I’m having trouble generating random numbers that do not follow a discrete uniform distribution.
So for example, say I have 5 numbers (to keep it simple), a probability of number k being generated would be k/15. (k = 1 to 5)
My idea is to generate a random number j using rand(), and if this number j is:
1 => then number 1 is generated
2 or 3 => num 2
4 or 5 or 6 => num 3
7 or 8 or 9 or 10 => num 4
11 or 12 or 13 or 14 or 15 => num 5
Now scale this to generating 1-10, 1-100, 1-1000. Does this work the way I intend it to? I’ve constructed a loop that pretty much does this every time a number needs to be generated, I think it’s probably inefficient since it goes up until it finds the j number generated in one of the ranges… What could be a better way to do this?
EDIT: or maybe create an array once with the proper numbers and then pull out with rand() better solution?
Consider that the sum
sof integers from 1 toniss = n * (n + 1) / 2. Solve fornto getn = (± sqrt(8*s + 1) - 1) / 2. We can ignore the negative square root, as we knownis positive. Thusn = (sqrt(8*s + 1) - 1) / 2.So, plugging in integers for
sbetween 1 and 15:If we take the ceiling of each computed
n(the smallest integer not less thann), we get this:Thus you can go from the uniform distribution to your distribution in constant space and constant time (no iteration and no precomputed tables):
N.B. This relies on
sqrtgiving an exact result for a perfect square (e.g. returning exactly 7 given exactly 49). This is normally a safe assumption, because IEEE 754 requires exact rounding of square roots.IEEE 754 doubles can represent all integers from 1 through 2^53 (and many larger integers, but not contiguously after 2^53). So this function should work correctly for all
sfrom 1 tofloor((2^53 - 1) / 8) = 1125899906842623.