2010-12-22 168 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