2010-12-22 164 views
9

下面是一个基本实现Xorshift RNG的(从维基百科复制):在Xorshift随机数生成算法

uint32_t xor128(void) { 
    static uint32_t x = 123456789; 
    static uint32_t y = 362436069; 
    static uint32_t z = 521288629; 
    static uint32_t w = 88675123; 
    uint32_t t; 

    t = x^(x << 11); 
    x = y; y = z; z = w; 
    return w = w^(w >> 19)^(t^(t >> 8)); 
} 

我明白w是返回值和xyz是国家( “内存”)变量。但是,我无法理解多个内存变量的用途。任何人都可以解释我这点吗?

另外,我试图复制上面的代码到Python:

class R2: 
    def __init__(self): 
     self.x = x = 123456789 
     self.y = 362436069 
     self.z = 521288629 
     self.w = 88675123 
    def __call__(self): 
     t = self.x^(self.x<<11) 
     self.x = self.y 
     self.y = self.z 
     self.z = self.w 
     w = self.w 
     self.w = w^(w >> 19) ^(t^(t >> 8)) 
     return self.w 

然后,我已经生成100个号码,并绘制其log10值:

r2 = R2() 
x2 = [math.log10(r2()) for _ in range(100)] 
plot(x2, '.g') 

这里是图的输出:

plot

和TH是10000(而不是100)数字生成时发生的情况: plot

整体趋势非常明显。并且不要忘记Y轴是实际值的log10

很奇怪的行为,你不觉得吗?

+0

的日志10输出应该已经是你的线索,最高32位的日志10是9.something,而不是100。 – 2010-12-22 11:52:51

回答

18

这里的问题当然是你使用Python来做到这一点。

Python有一个大整数的概念,所以即使你正在复制一个处理32位数的实现,Python只会说“我会继续为你保留所有的东西”。

如果你试试这个来代替:

x2 = [r2() for _ in range(100)] 
print(x2); 

你会发现,它会产生不断长号码,例如这里的第一个数字:

252977563114 

和这里的最后一个:

8735276851455609928450146337670748382228073854835405969246191481699954934702447147582960645 

下面是已经修复的代码:

... 
def __call__(self): 
    t = self.x^(self.x<<11) & 0xffffffff     # <-- keep 32 bits 
    self.x = self.y 
    self.y = self.z 
    self.z = self.w 
    w = self.w 
    self.w = (w^(w >> 19) ^(t^(t >> 8))) & 0xffffffff # <-- keep 32 bits 
    return self.w 
... 
2

“但是,我无法理解多个内存变量的目的” - 如果您需要“记住”128位,那么您需要4 x 32位整数。

至于100个randoms的非常奇怪的分布,不知道!我可以理解,如果你已经生成了几百万,并且图中的步骤是工件,但不是100.

4

并具有生成:

def xor128(): 
    x = 123456789 
    y = 362436069 
    z = 521288629 
    w = 88675123 
    while True: 
    t = (x^(x<<11)) & 0xffffffff 
    (x,y,z) = (y,z,w) 
    w = (w^(w >> 19)^(t^(t >> 8))) & 0xffffffff 
    yield w