使用Boost的C ++-11中的封装随机数生成器 [英] Encapsulated Random number generator in C++-11 using boost

查看:436
本文介绍了使用Boost的C ++-11中的封装随机数生成器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用boost在C ++-11中生成随机数.我看到了一些与此相关的不错的文章,并且能够生成随机数,将我的所有代码放入主函数中,如本网页中所建议的那样(增强随机数生成器)./p>

我实现了以下代码.但它在失败上都失败了:随机种子的更改和值范围的定义.

#include <boost/random/variate_generator.hpp>
#include <boost/generator_iterator.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/normal_distribution.hpp>

typedef boost::mt19937                     ENG;    // Mersenne Twister
typedef boost::normal_distribution<double> DIST;   // Normal Distribution
typedef boost::variate_generator<ENG,DIST> GEN;    // Variate generator

class RNG {

  private:
     ENG eng;
     DIST dist;

  public:
     GEN gen;
     RNG(double min,double max,int seed)
     : dist(min,max), gen(eng,dist)
     {eng.seed(seed); }
};

这是我的主要功能.

int main(int argc, char **argv){
    if(argc == 2){
        int myseed = atoi(argv[1]);
        double minimum = 1.;
        double maximum = 10.;
        int N = 20;

        RNG myrn(minimum,maximum,myseed);

        for (int i = 0; i < N; i++){
            std::cout << myrn.gen() << std::endl;
        }
            return 0;
    }
    exit(1);
}

此实现独立于我使用的种子生成相同的随机数序列.另外,随机数不在最小值和最大值之间的范围内.你们当中有人知道如何解决这两个问题吗?

解决方案

boost::variate_generator 按值接受其构造函数参数,因此当您将其传递给mem-initializer列表中的默认构造的mt19937时,它会对其进行复制.将引擎播种到构造函数的主体中将对该副本无效.要解决此问题,请将模板参数类型更改为引用.

typedef boost::variate_generator<ENG&,DIST> GEN;
//                                  ^

接下来,我认为您不需要 uniform_real_distribution .

typedef boost::random::uniform_real_distribution<> DIST;

进行了这些修复之后,您的代码应具有预期的作用.

实时演示


使用C ++ 11编译器,甚至不需要Boost, <random> 标头提供了您需要的所有组件.唯一的显着区别是缺少variate_generator类,当您想生成随机数时,可以使用引擎作为参数来调用分发对象.

#include <random>

typedef std::mt19937                     ENG;    // Mersenne Twister
typedef std::uniform_real_distribution<> DIST;   // Uniform Distribution

class RNG {

  private:
     ENG eng;
     DIST dist;

  public:
     DIST::result_type gen() { return dist(eng); }
     RNG(double min,double max,int seed)
     : dist(min,max)
     {eng.seed(seed); }
};

实时演示

I am trying to generate random numbers in C++-11 using boost. I have seen some nice posts about this and I was able to generate random numbers putting all my code in the main function, like suggested in this webpage (http://www.sitmo.com/article/generating-random-numbers-in-c-with-boost/).

However, I was not able to encapsulate a random number generator (RNG) that can be called by different functions. I would like this encapsulated RNG to receive as parameters the range of numbers and a random seed. I tried to do it by following the suggestions of this post (Boost random number generator).

I implemented the code below. But it fails in both: the change of random seed and the definition of the range of values.

#include <boost/random/variate_generator.hpp>
#include <boost/generator_iterator.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/normal_distribution.hpp>

typedef boost::mt19937                     ENG;    // Mersenne Twister
typedef boost::normal_distribution<double> DIST;   // Normal Distribution
typedef boost::variate_generator<ENG,DIST> GEN;    // Variate generator

class RNG {

  private:
     ENG eng;
     DIST dist;

  public:
     GEN gen;
     RNG(double min,double max,int seed)
     : dist(min,max), gen(eng,dist)
     {eng.seed(seed); }
};

And this is my main function.

int main(int argc, char **argv){
    if(argc == 2){
        int myseed = atoi(argv[1]);
        double minimum = 1.;
        double maximum = 10.;
        int N = 20;

        RNG myrn(minimum,maximum,myseed);

        for (int i = 0; i < N; i++){
            std::cout << myrn.gen() << std::endl;
        }
            return 0;
    }
    exit(1);
}

This implementation generates the same sequence of random numbers independently of the seed I use. Also, the random numbers are not in the range between minimum and maximum. Does any of you know how to fix these two issues?

解决方案

boost::variate_generator takes its constructor arguments by value, so when you pass it a default constructed mt19937 in the mem-initializer list it makes a copy of it. Seeding the engine within the body of the constructor will have no effect on that copy. To fix this, change the template argument type to a reference.

typedef boost::variate_generator<ENG&,DIST> GEN;
//                                  ^

Next, I don't think you want a normal_distribution, its constructor arguments are not the minimum and maximum of the range of values produced by the distribution, but the mean and standard deviation of the distribution.

The distribution you're probably looking for is uniform_real_distribution.

typedef boost::random::uniform_real_distribution<> DIST;

After making these fixes, your code should behave as you want it to.

Live demo


With a C++11 compiler you don't even need Boost to do this, the <random> header provides all the components you need. The only significant difference is the lack of a variate_generator class, instead you invoke the distribution object using the engine as the argument when you want to generate a random number.

#include <random>

typedef std::mt19937                     ENG;    // Mersenne Twister
typedef std::uniform_real_distribution<> DIST;   // Uniform Distribution

class RNG {

  private:
     ENG eng;
     DIST dist;

  public:
     DIST::result_type gen() { return dist(eng); }
     RNG(double min,double max,int seed)
     : dist(min,max)
     {eng.seed(seed); }
};

Live demo

这篇关于使用Boost的C ++-11中的封装随机数生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆