为了更好地理解mersennetwister(MT),我决定将其转换成python。Here您可以运行代码并在底部看到注释的C源代码。在
代码运行,但我没有得到预期的输出。基于C输出here,我应该得到的第一个数字是1067595299 955945823 477289528 4107218783 4228976476
,但是我得到的是{
旁注:
我在上面找到了另一个实现,说它们得到了与C here相同的输出,但是当我在python2或python3(xrange->;范围,十六进制中没有L)时,输出也与预期的Cs不匹配,它给出了0.817330 0.999061 0.510354 0.131533 0.035416
,而不是预期的0.76275443 0.99000644 0.98670464 0.10143112 0.27933125
。。。如果您想更改我的代码以在[0,1]内给出一个结果,那么interval将给出0.6039989429991692 0.8493715333752334 0.15547331562265754 0.9237168228719383 0.823132110061124
,这两个结果也不同。在
为什么这个python代码不能提供与C代码相同的输出?我是不是错误地执行了某件事?在
代码:
class RandomGenerators:
# period parameters
N = 624
M = 394
MATRIX_A = 0x9908b0df # constant vector a
UPPER_MASK = 0x80000000 # most significant w-r bits
LOWER_MASK = 0x7fffffff # least significant r bits
def __init__(self):
self.mt = [None]
self.mti = self.N + 1
'''
initialize by an array with array-length
init_key is the array for initializing keys
key_length is its length
slight change for C++, 2004/2/26
'''
def init_by_array(self, init_key, key_length):
#int i, j, k;
self.init_genrand(19650218)
i,j = 1,0
k = self.N if self.N > key_length else key_length
#k = (self.N > key_length ? self.N : key_length)
#for (; k; k--) {
while k > 0:
self.mt[i] = (self.mt[i] ^ ((self.mt[i-1] ^ (self.mt[i-1] >> 30)) * 1664525)) + init_key[j] + j # non linear
self.mt[i] &= 0xffffffff # for WORDSIZE > 32 machines
i+=1
j+=1
if i >= self.N:
self.mt[0] = self.mt[self.N-1]
i = 1
if j >= key_length:
j = 0
k-=1
k = self.N-1
#for (k=N-1; k; k--) {
while k > 0:
self.mt[i] = (self.mt[i] ^ ((self.mt[i-1] ^ (self.mt[i-1] >> 30)) * 1566083941)) - i # non linear
self.mt[i] &= 0xffffffff # for WORDSIZE > 32 machines
i += 1
if i >= self.N:
self.mt[0] = self.mt[self.N-1]
i=1
k-=1
self.mt[0] = 0x80000000 # MSB is 1; assuring non-zero initial array
# initializes mt[N] with a seed
def init_genrand(self,s):
self.mt[0] = s & 0xffffffff
self.mti = 1
while self.mti < self.N:
self.mt.append(1812433253 * (self.mt[self.mti-1] ^ (self.mt[self.mti - 1] >> 30)) + self.mti)
self.mt[self.mti] &= 0xffffffff
self.mti += 1
# generates a random number on [0,0xffffffff]-interval
def genrand_int32(self):
y = 0
mag01=[0x0, self.MATRIX_A]
if self.mti >= self.N: # generate N words at one time
kk = 0
if self.mti == self.N + 1: # if init_genrand() has not been called,
self.init_genrand(5489) # a default initial seed is used
while kk < self.N - self.M:
y = (self.mt[kk] & self.UPPER_MASK) | (self.mt[kk+1] & self.LOWER_MASK)
self.mt[kk] = self.mt[kk+self.M] ^ (y >> 1) ^ mag01[y & 0x1]
kk += 1
while kk < self.N - 1:
y = (self.mt[kk] & self.UPPER_MASK) | (self.mt[kk+1] & self.LOWER_MASK)
self.mt[kk] = self.mt[kk+(self.M-self.N)] ^ (y >> 1) ^ mag01[y & 0x1]
kk += 1
y = (self.mt[self.N-1] & self.UPPER_MASK) | (self.mt[0] & self.LOWER_MASK)
self.mt[self.N-1] = self.mt[self.M-1] ^ (y >> 1) ^ mag01[y & 0x1]
self.mti = 0
y = self.mt[self.mti]
self.mti += 1
# Tempering
y ^= (y >> 11)
y ^= (y << 7) & 0x9d2c5680
y ^= (y << 15) & 0xefc60000
y ^= (y >> 18)
return y
# generates a random number on [0,0x7fffffff]-interval
def genrand_int31(self):
#return (long)(genrand_int32() >> 1)
return (self.genrand_int32() >> 1)
# generates a random number on [0,1]-real-interval
def genrand_real1(self):
return self.genrand_int32() * (1.0 / 4294967295.0)
# divided by 2^32-1
# generates a random number on [0,1)-real-interval
def genrand_real2(self):
return self.genrand_int32() * (1.0 / 4294967296.0)
# divided by 2^32
# generates a random number on (0,1)-real-interval
def genrand_real3(self):
return ((self.genrand_int32()) + 0.5) * (1.0 / 4294967296.0)
# divided by 2^32
# generates a random number on [0,1) with 53-bit resolution
def genrand_res53(self):
a, b = self.genrand_int32()>>5, self.genrand_int32()>>6
return(a * 67108864.0 + b) * (1.0 / 9007199254740992.0)
r = RandomGenerators()
init = [0x123, 0x234, 0x345, 0x456]
length = 4
r.init_by_array(init, length)
for i in range(10):
print('mt: '+str(r.genrand_int32()))
--编辑--
mt[]
值未正确初始化。调用init_by_array
后C中的前几个值是:
在python中,前几个是:
2147483648
1827812183
1371430253
3559376401
所以看来问题出在正/负十六进制上。我修改了init_by_array
here下面的代码,但我猜{
for i,num in enumerate(self.mt):
if num>=2147483648: # (2**32)/2
self.mt[i]-=4294967296 # 2**32
目前没有回答
相关问题 更多 >
编程相关推荐