赞 | 3 |
VIP | 4 |
好人卡 | 4 |
积分 | 1 |
经验 | 8941 |
最后登录 | 2015-8-17 |
在线时间 | 182 小时 |
Lv1.梦旅人
- 梦石
- 0
- 星屑
- 50
- 在线时间
- 182 小时
- 注册时间
- 2012-2-11
- 帖子
- 233
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 viktor 于 2012-11-8 14:29 编辑
嗯……其实ruby1.7以上的srand/rand函数本身就是用的mersenne twister产生的强随机数
其实ruby1.9自带了Random类,但是XP用的ruby1.81没有
总之 反正照着标准C程序mt19937ar.c抄了一份ruby的,可以制定随机数种子 和初始向量的随机数产生器。
用法
mt = MT19937.new(seed) # seed是随机数种子
iv = [123, 456, 789, 1234, 5678] ¥ iv是初始向量,想填几个数字都行,自由发挥
mt.init_array iv # 可以在用种子初始化的基础上,再定义初始向量,增强随机性
随机数:
mt.randi
另外底下的常数除了birthday是原作者的生日(作者自重)以外其他都不要改了。后果貌似很严重……
- #============
- # rpg.blue
- # Mersenne Twister copycat version.
- # original: mt19937ar.c
- # author: viktor
- #============
- class MT19937
- N = 624
- M = 397
- A = 0x9908b0df
- MASK_S32 = 0x7fffffff
- MASK_U32 = 0xffffffff
- PRIMITIVE = 1812433253
- BIRTHDAY = 19650218
- MAGIC = [166_4525, 156_608_3941, 0x9d2c5680, 0xefc60000]
-
- attr_reader :seed
- attr_reader :iv
- def init_mt(s)
- @mt[0] = s & MASK_U32
- N.times{|i|@mt[i+1]=(PRIMITIVE * (@mt[i] ^ (@mt[i] >> 30))+i+1) & MASK_U32}
- @life = N
- end
-
- def init_array(iv)
- @iv = iv
- i, j = 1, 0
- [iv.length, N].max.times {
- @mt[i] = (@mt[i] ^ (( @mt[i-1] ^ (@mt[i-1] >> 30 )) * MAGIC[0]))
- @mt[i] =(@mt[i]+iv[j]+j) & MASK_U32
- i+=1; j=(j+1) % iv.length
- if i>=N
- @mt[0] = @mt[N-1] # 折叠数组
- i=1
- end
- }
- (N-1).times {
- @mt[i] = (@mt[i] ^ (( @mt[i-1] ^ (@mt[i-1] >> 30 )) * MAGIC[1]))
- @mt[i] =(@mt[i]-i) & MASK_U32
- i+=1; if i>=N
- @mt[0] = @mt[N-1]
- i=1
- end
- }
- @mt[0] = 0x80000000
- end
-
- def randi
- if @life >= N
- # start a new round, update table mt
- N.times {|k|
- tmp = (@mt[k] & 0x80000000) | (@mt[(k+1)%N] & MASK_S32)
- @mt[k] = @mt[(k+M)%N] ^ (tmp>>1) ^ (tmp[0]*A)
- }
- @life=0
- end
- ret = @mt[@life]
- ret ^= (ret >> 11);
- ret ^= (ret << 7) & MAGIC[2];
- ret ^= (ret << 15) & MAGIC[3];
- ret ^= (ret >> 18);
- @life+=1
- ret
- end
-
- def initialize(seed=nil)
- @mt=[]
- srand(seed)
- end
-
- def srand(seed=nil)
- last_seed = @seed
- seed = rand(1<<32) if seed==nil
- @seed = seed
- init_mt(@seed)
- return last_seed
- end
- end
- # test
- mt = MT19937.new(MT19937::BIRTHDAY)
- iv = [0x123, 0x234, 0x345, 0x456]
- mt.init_array iv
- out = []
- 1000.times {out << mt.randi}
- p out
复制代码 |
|