2011-03-29 101 views
0

其实,我有几个交织问题。 (如果它很重要,我使用C#)。缩放Int内统一的随机范围变成双数

首先。我有一个在UInt32范围内产生随机数的prng,从0到UInt32.Max(含)。我想尽可能保持一致性。 (a,b),双重范围(如[0,1],[0,1),(0,1),[-2,4],( - 10,10))?

我很关心以下内容。我有4 294 967 296个成果。它小于[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,1]。为了得到(0,1),我考虑(2^53) - 2个新的结果并将1 /(2^53)加到0为基础的结果。得到接近或等于整个双倍范围的双倍范围?即使我构造如上所述的n元数,它可能会变得比Double.Max大。可能有些位移/位掩码方法有可能吗?

其次。现在在[0,1)中有双重结果,可以得到[Double.Min,Double.Max]范围吗?有多少个双数?如果有完整的双倍范围prng,获得UInt范围的最佳方式是什么?直接映射或直接映射到[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,为什么之后a * 67108864.0 + b是统一的?

谢谢。

回答

1

良好的随机数发生器在所有位置产生随机位。某些类别的穷程序在低阶位中产生较差的随机性。因此,如果您需要53位并生成64位,那么您希望丢弃11位最低位 - 在您发布的示例代码中,5位来自一位数字,5位来自另一位数字。现在你有一个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)再次选择。无论如何,你的随机数发生器可能没有足够长的时间段。

相关问题