Actually, I have several interweaving questions. (If it matters I use C#.)
First. I have a prng that generates random numbers in UInt32 range, from 0 to UInt32.Max inclusive. I want to preserve the uniformity as much as possible. What is the main idea to get [a,b], (a,b) double ranges (such as [0,1], [0,1), (0,1), [-2,4], (-10,10))?
I'm concerned about the following. I have 4 294 967 296 prng outcomes. It is less than numbers in [0,1] double range — 2^53. So I construct 4 294 967 296-ary number from 2 digits, which is random and uniform in [0, 4294967295 * 4294967296 + 4294967295]. This maximum value is larger than 2^53 on 1 so if one get it one throw it away, recalculate, use mod 2^53 and get uniform number in, for example, [0,1]. Here I have to represent the maximum value as double (suppose there is no Int64 type) — are there any drawbacks with it?
Now, if I want get [0,1), I consider that the number of outcomes is (2^53) - 1. Adding to the last result 1/(2^53) will produce random double in (0,1]. To get (0,1) I consider (2^53) - 2 new outcomes and add 1/(2^53) to 0-based result. Is all that correct?
But how to get double ranges that are close or equal to the whole double range? Even If I construct n-ary number like above, it may become larger than Double.Max. May be some bitshifts/bitmasks approach is possible?
Second. Now there is double prng with outcomes in [0,1) is that possible to get [Double.Min, Double.Max] range? How many double numbers at all? If there is full double range prng, what is the best way to get UInt range — map "directly" or scale to [0,1] before?
Third. I found this code (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c):
/* generates a random number on [0,1) with 53-bit resolution*/
double genrand_res53(void)
{
unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
return(a*67108864.0+b)*(1.0/9007199254740992.0);
}
Why a and b are shifted to 5 and 6 and why after that a*67108864.0+b is uniform?
Thank you.