【问题标题】:c++ Boost random ints from multiple ranges using single generatorc++ 使用单个生成器从多个范围提升随机整数
【发布时间】:2016-06-22 15:59:31
【问题描述】:

使用boost::random 我正在尝试从不同范围内对一组均匀分布的整数进行采样,但使用相同的底层随机数生成器。对于每个范围,我定义了一个返回随机数的不同函数。 但是,似乎每个函数都返回相同的数字。

说明该方法的示例:

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/random.hpp>

struct RandomNumberGenerator {
  boost::mt19937 generator;

  RandomNumberGenerator(long seed) {
    generator.seed(seed);
  }

  boost::function<int()> getRandomFunctionInt(int min, int max) {
    boost::uniform_int<> uni_dist(min, max);
    boost::variate_generator<boost::mt19937&, boost::uniform_int<> > uni(generator, uni_dist);

    boost::function<int()> f;
    f = boost::bind(uni_dist, generator);
    return f;
  }
};

int main (int argc, char* argv[]) {
  RandomNumberGenerator rng(1729);
  boost::function<int()> runif1 = rng.getRandomFunctionInt(0,  1000);
  boost::function<int()> runif2 = rng.getRandomFunctionInt(0, 10000);

  for (int i=0; i<10; ++i) {
    std::cout << runif1() << ", " << runif2() << std::endl;
  }
}

输出是:

212, 2121
623, 6226
259, 2590
[...]

有什么方法可以取消函数的关联吗?为了我的实验的可重复性,我想使用单个种子。

【问题讨论】:

    标签: c++ boost random


    【解决方案1】:
    f = boost::bind(uni_dist, generator);
    

    您需要将引用传递给生成器。现在,您正在传递生成器的副本,这意味着每个f 对象都有一个处于初始状态的生成器副本。

    f = boost::bind(uni_dist, boost::ref(generator));
    

    使用 Lambda 的不同版本会使歧义更加明显(并且更容易检测/解决):

    f = [uni_dist, this] {return uni_dist(generator);};
    

    此外,c++11 引入了 &lt;random&gt; 标头,它提供了与 boost 的 random 标头提供的所有相同的功能和更多功能,因此没有任何理由继续使用 boost 版本。

    【讨论】:

    • 感谢您指出我的菜鸟错误...回答接受并赞赏!切换到标准的&lt;random&gt; 标头也是不错的建议。 +1 用于使用 lambda 函数的解决方案 - 不过有一个小问题:在 C++11 中,成员变量(如 generator)无法直接捕获,必须求助于局部变量并捕获该变量:boost::mt19937 &amp;g = generator跨度>
    • @mrhd 我认为如果您捕获this,则可以捕获成员变量。我已经修改了答案以解决这个问题。
    • 感谢您的更新,您的解决方案更加简洁。我现在意识到确实是 boost::bind() 复制了一个副本,因为您不需要在 uni_dist(generator) 中通过引用传递。
    猜你喜欢
    • 1970-01-01
    • 2023-03-04
    • 2010-09-22
    • 1970-01-01
    相关资源
    最近更新 更多