【问题标题】:mt19937 and uniform_real_distributionmt19937 和 uniform_real_distribution
【发布时间】:2015-02-06 22:38:27
【问题描述】:

我正在尝试找到一种有效的方法来实现统一 (0,1) 分布。由于我要生成非常多的样本,所以我选择了 mt19937 作为引擎。我正在使用 boost 库中的版本。我的问题是:使用引擎本身的输出与使用 uniform_real_distribution 有什么区别?

选项 #1

std::random_device rd;
boost::mt19937 gen(rd());
boost::random::uniform_real_distribution<double> urand(0, 1);

for ( int i = 0; i < 1E8; i++ ) {
    u = urand(gen);
}

选项 #2

std::random_device rd;
boost::mt19937 gen(rd());

for ( int i = 0; i < 1E8; i++ ) {
    u = (double) gen()/gen.max();
}

根据我的测试,选项 #2 在运行时方面比选项 #1 好得多。有什么理由我应该选择选项 #1 而不是选项 #2?

【问题讨论】:

  • 不看实现本身就不可能确定,但​​我假设uniform_real_distribution 使用更多位来确保可以返回范围内的每个可能的浮点结果。选项 #2 的孔间距为 1/gen.max()。

标签: c++ boost prng mersenne-twister


【解决方案1】:

我不知道urand() 的底层实现,但是使用除法的结果很可能会在低位产生偏差作为量化效果。如果gen.max() 不大,那么“低位”可能是结果的很多或大部分位。

性能差异可能来自产生正确分布的随机数。如果double 过于精确地满足您的需求,那么使用float 可能会使其运行效率更高。

【讨论】:

    【解决方案2】:

    我的问题是:使用引擎本身的输出与使用 uniform_real_distribution 有什么区别?

    在您的第一个选项中,urand() 的范围为 [0,1),而您的第二个选项的范围为 [0,1](如果 boost::mt19937::min() == 0,通常成立)。

    【讨论】:

    • 谢谢!我没有注意到范围的差异。那么从随机数生成器的性能和质量来看,第二个选项似乎更好?
    猜你喜欢
    • 2012-11-09
    • 2017-10-12
    • 2018-03-28
    • 1970-01-01
    • 1970-01-01
    • 2018-08-02
    • 2013-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多