Skip to content

Instantly share code, notes, and snippets.

@dutc
Created July 19, 2013 03:46
Show Gist options
  • Save dutc/6034974 to your computer and use it in GitHub Desktop.
Save dutc/6034974 to your computer and use it in GitHub Desktop.
mersenne twister pseudo-random number generator
from __future__ import division
# ref: en.wikipedia.org/wiki/Mersenne_twister
def mersenne(seed = 1, period=397, length=624):
state, tm = [seed & 0xffffffff], lambda op, x: x ^ op(x)
for i in xrange(1,length):
state.append((0x6c078965 * (state[-1] ^ (state[-1] >> 30)) + i) & 0xffffffff)
while True:
for i in xrange(length):
y = (state[i] & 0x80000000) + (state[(i+1)%length] & 0x7fffffff)
state[i] = (state[(i+period)%length] ^ (y >> 1)) ^ (0x9908b0df if y%2 else 0)
for i in xrange(length):
yield tm(lambda x: x >> 18, tm(lambda x: (x << 15) & 0xefc60000, tm(lambda x: (x << 7) & 0x9d2c5680, tm(lambda x: x >> 11, state[i]))))
from itertools import takewhile
def randrange(start, stop, mersenne=mersenne(seed=1)):
size = 2**32 // (stop - start)
return start + next(takewhile(lambda x: 0 <= x < (stop-start)*size,mersenne)) % (stop-start)
if __name__ == '__main__':
from itertools import islice
m = mersenne(seed=1)
assert list(islice(m,0,10)) == [1791095845, 4282876139, 3093770124, 4005303368, 491263, 550290313, 1298508491, 4290846341, 630311759, 1013994432]
from collections import Counter
sample = Counter(randrange(1,13,m) for _ in xrange(10000))
for x in xrange(1,13):
print '{:>3} {:.3f}'.format( x, sample[x] / 10000 )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment