首页 > 代码库 > 关于随机数分布器的问题

关于随机数分布器的问题

今天看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;

噢,原来是梅森螺旋算法啊~,当时想用的时候不知道尖括号里都该填什么,这下有两个现成的可用了。

 

关于随机数分布器的问题