将Int均匀随机范围缩放为Double 1

时间:2011-03-29 12:02:28

标签: algorithm random prng

实际上,我有几个交织问题。 (如果重要的话我使用C#。)

首先。我有一个prng,它在UInt32范围内生成随机数,从0到UInt32.Max包含。我想尽可能保持均匀性。获得[a,b],(a,b)双重范围(如[0,1],[0,1),(0,1),[ - 2,4],( - )的主要思路是什么? 10,10))?

我关注以下内容。我有4 294 967 296 prng结果。它小于[0,1]双范围内的数字 - 2 ^ 53。因此,我从2位数构造4 294 967 296-ary数,这在[0,4294967295 * 4294967296 + 4294967295]中是随机且均匀的。这个最大值在1上大于2 ^ 53所以如果一个得到它扔掉它,重新计算,使用mod 2 ^ 53并得到统一数字,例如,[0,1]。在这里,我必须将最大值表示为double(假设没有Int64类型) - 它有任何缺点吗?

现在,如果我想得到[0,1],我认为结果的数量是(2 ^ 53) - 1.添加到最后的结果1 /(2 ^ 53)将产生随机双倍(0)为了得到(0,1),我考虑(2 ^ 53) - 2个新结果,并将1 /(2 ^ 53)加到基于0的结果。是否正确?

但是如何获得接近或等于整个双倍范围的双倍范围?即使我像上面那样构造了n-ary数,它也可能比Double.Max更大。可能是一些bithifts / bitmasks方法可能吗?

二。现在有一个双重prng与[0,1)的结果是可以得到[Double.Min,Double.Max]范围?有多少双数?如果有完整的双范围prng,获得UInt范围的最佳方法是什么 - 直接映射到“[0,1]”之前还是缩放到[0,1]?

第三。我找到了这段代码(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); 
 } 

为什么a和b转移到5和6以及为什么之后* 67108864.0 + b是均匀的?

谢谢。

1 个答案:

答案 0 :(得分:1)

好的随机数生成器在所有位置产生随机位。某些类别的穷人在低阶位中产生差的随机性。因此,如果您需要53位并生成64,则需要丢弃11个最低位 - 在您发布的示例代码的情况下,5个来自一个数字,6个来自另一个数字。现在你有一个26位数字和一个27位数字; 2 ^ 26是67108864,2 ^ 53是9007199254740992,这应该解释为什么这些常数用于将这些数字缩放为[0,1)。 (这是一个混合基数:第一个数字为67108864-ary,第二个数字为134217728-ary。)

(经常使用53位的原因是它使数字在减法时对称 - 否则,当你从1减去它们时,2 ^ -53和2 ^ -64之间的值将消失。)

此外,当你有太多的位时你不应该重新取样 - 只丢掉多余的位(除非你少于一个)。

无论如何,明显的方法给你[0,1)。如果你想要(0,1)那是1 - [0,1)。如果你想要(0,1),如果得到a = 0和b = 0,再次采样。如果你想要[0,1],请注意得到1的概率为1(2 ^ 53 + 1),否则你有[0,1]。您可以通过在[0,1)中获取一个随机数并检查它是否为零来进行近似,如果是,则选择1作为答案,如果不是,则从[0,1)中再次选择。您的随机数生成器可能没有足够长的时间来确保比此更精确。