关于随机数分布器的问题
今天看C++Primer介绍的随机数,准备使用一下,结果出现点小问题,就是每次运行程序获得的首个随机数都是一样的。
(已使用time作为随机数种子,按理说应该至少每秒产生的随机数都是不一样的)
int main() { default_random_engine e(time(0)); uniform_int_distribution<unsigned> u(0,99); cout<<u(e)<<endl; }
如果直接输出e()那么会产生0-2147483646之间的随机数,程序每次运行,至少每秒运行产生的随机数都不一样。
但是用了分布器之后,u(e)输出的第一个值总是一样的。通过手动传入种子,可以知道相近的种子产生的第一个随机值
也是相近的,那分布器到底对原始值做了怎样的压缩呢?
int main() { default_random_engine e; uniform_int_distribution<unsigned> u(0,99); for(size_t i = 0; i < 100000; ++i) { e.seed(i); if(u(e) != 0) { cout<<i<<endl; break; } } cout<<"0-9:"<<12778.0/60.0<<endl; cout<<"0-99:"<<1278.0/60.0<<endl; cout<<"0-999:"<<128.0/60.0<<endl; }
程序输出i的值为1278,也就是说种子0-1277产生的随机数经过u(0,99)压缩后得到的都是0,呃,那么也就是说
如果用time(0)作为种子,产生0-99之间的随机数,可能程序最多在1277秒内产生的第一个随机值都是一样的。
如果程序运行一次,关掉,再运行一次,结果却一样。。。
其它测试:0-9 12777秒; 0-999 127秒
这应该是生成器算法的问题吧,相近的种子产生相近的随机值,分布器对一定范围的随机值压缩成一个值。。。
结果就是一段时间内的首个随机值都一样。。。真杯具
解决办法,丢掉第一个值,呃。那么换个生成器试试
int main() { mt19937 e(time(0)); uniform_int_distribution<unsigned> u(0,99); cout<<u(e); }
这次的结果还算可以接受,每次都不一样了,搜了一下mt19937的介绍,结果msdn上有
typedef mersenne_twister_engine<unsigned int, 32, 624, 397, 31, 0x9908b0df, 11, 0xffffffff, 7, 0x9d2c5680, 15, 0xefc60000, 18, 1812433253> mt19937; typedef mersenne_twister_engine<unsigned long long, 64, 312, 156, 31, 0xb5026f5aa96619e9ULL, 29, 0x5555555555555555ULL, 17, 0x71d67fffeda60000ULL, 37, 0xfff7eee000000000ULL, 43, 6364136223846793005ULL> mt19937_64;
噢,原来是梅森螺旋算法啊~,当时想用的时候不知道尖括号里都该填什么,这下有两个现成的可用了。