实际上,我有几个交织的问题(如果重要,我用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位数字构造了4294967295*4294967296+4294967295中随机均匀的4229496296元数。这个最大值在1上大于2 ^ 53,所以如果一个得到它,把它扔掉,重新计算,使用mod 2 ^ 53,得到均匀的数字,例如,[0,1]。这里,我必须将最大值表示为两倍(假设没有In64类型)-它有什么缺点吗?
现在,如果我想得到[0,1],我认为结果的数目是(2^53)-1。加上最后的结果1/(2^53)将产生随机双入(0,1)。为了得到(0,1),我考虑(2^53)-2个新结果,并将1/(2^53)添加到基于0的结果中。这些都对吗?
但是如何得到接近或等于整个双倍范围的双倍范围呢?即使我构造了如上所述的n元数,它可能会变得大于double.max。可能有一些位移/位掩码方法是可能的?
第二。现在有双prng,其结果在[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是均匀的?
谢谢您。
最佳答案
好的随机数生成器在所有位置产生随机位某些类别的差比特在低阶比特中产生很差的随机性。因此,如果您需要53位并生成64位,那么您需要丢弃11个最低顺序的位——在您发布的示例代码中,5个来自一个数字,6个来自另一个数字。现在你有一个26位数字和一个27位数字;2^26是67108864,2^53是9007199254740992,这就解释了为什么这些常数被用来将这些数字缩放成[0,1](这是一个混合基数:第一位67108864元,第二位134217728元。)
(通常使用53位的原因是,它使数字在减法时对称——否则,从1减去2^-53和2^-64之间的值时将消失。)
另外,当你有太多的比特时,你不应该重新采样——只要扔掉多余的比特(除非你有少于一个的比特)。
不管怎样,显而易见的方法给出了[0,1]如果你想要(0,1),那是1-[0,1]。如果需要(0,1),如果同时得到a=0和b=0,则再次采样。如果您想要[0,1],请注意(2^53+1)中有1的机会获得1,否则就有[0,1]你可以通过在0,1中得到一个随机数来检验它是否为零,然后选择1作为答案,如果是,或者选择0(0)。你的随机数生成器可能没有足够长的时间比这更精确。
关于algorithm - 将Int均匀随机范围缩放为Double一,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5472156/