C ++ OOP:如何创建随机数生成器对象?

时间:2016-08-27 16:24:00

标签: python c++ oop

所以这个问题就像翻译一样。我是C ++的新手,正在查看类文档。但是,看起来通过文档找到我的问题的答案有点困难。

我有用于在C ++中生成介于0和1之间的随机数的代码:(从here获得,因为浮点数的rand()函数解是基于整数的)

#include <random>
#include <iostream>

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(0, 1); //corrected from 1,2
    for (int n = 0; n < 10; ++n) {
        std::cout << dis(gen) << ' ';
    }
    std::cout << '\n';
}

接下来,我想创建一个类或结构或其他东西(不是真正的OOP人),它具有以下API:

float x = my_RandomNumberGenerator.next();

在python中,我可能会写一些类似的东西:

class my_RNG():
    def __init__(self):
        self.rd = (the random device object I initialize in c code)
        self.gen = (the mersenne_twister engine object)(rd)
        self.distribution = (the uniform real distribution object)

    def next():
        return self.distribution(self.gen)

my_randomNumberGenerator = my_RNG()
print(my_randomNumberGenerator.next())

我如何在C ++中实现它?

更新这是我到目前为止所做的(它不起作用......或者编译......但是在我的模板代码中初始化事物的方式似乎有些奇怪我来自参考网站,我不明白):

#include <iostream>
#include <random>


class MyRNG
{
    public:
        float next(void);
    private:
        std::random_device randomDevice;
        std::mt19937_64 randomGenerator;
        std::uniform_real_distribution distribution;
        MyRNG(float range_lower,float range_upper);

};
MyRNG::MyRNG(float range_lower, float range_upper)
{
    randomGenerator = std::mersenne_twister_engine(randomDevice);
    distribution = std::uniform_real_distribution<> distribution(range_lower,range_upper);
}
MyRNG::next(void)
{
    return distribution(randomGenerator);
}

int main() {
    MyRNG my_rng = MyRNG(0,1);
    std::cout << my_rng.next() << std::endl;
    return 0;
}

2 个答案:

答案 0 :(得分:3)

您似乎只需要某种形式的概率生成类,请参阅下面的基本实现,以满足您的问题要求:

template<class Ty = double,
    class = std::enable_if_t<std::is_floating_point<Ty>::value>
> class random_probability_generator {
public:
    // default constructor uses single random_device for seeding
    random_probability_generator() 
        : mt_eng{std::random_device{}()}, prob_dist(0.0, 1.0) {}
    // ... other constructors with custom seeds if necessary
    Ty next() { return prob_dist(mt_eng); } 
    // ... other methods if necessary
private:
    std::mt19937 mt_eng;
    std::uniform_real_distribution<Ty> prob_dist;
};

然后你可以通过以下方式使用它:

random_probability_generator<> pgen;
double p = pgen.next(); // double in range [0.0, 1.0]

或者,如果您想要随机float(因为您的问题的一部分似乎暗示):

random_probability_generator<float> pgen;
float p = pgen.next(); // float in range [0.0f, 1.0f] 

另外,为了解决您发布的课程没有编译的原因,您的课程中的错误是您尝试使用{{1初始化std::mt19937_64类型对象(randomGenerator)实例但它们基本上是不同的类型。相反,你需要做

std::mersenne_twister_engine

randomGenerator = std::mt19937_64(randomDevice()); 构造函数中,或者通过初始化列表构建,就像我在上面的例子中所做的那样。

正如评论中所指出的,更合适的 c ++ - esque 实现是重载MyRNG而不是创建operator()方法。请参阅下文,以更好地实现上述类

next()

然后你可以在这个答案的第一堂课中使用它,

template<class FloatType = double,
    class Generator = std::mt19937,
    class = std::enable_if_t<std::is_floating_point<FloatType>::value>
> class uniform_random_probability_generator {
public:
    typedef FloatType result_type;
    typedef Generator generator_type;
    typedef std::uniform_real_distribution<FloatType> distribution_type;
    // default constructor
    explicit uniform_random_probability_generator(Generator&& _eng 
        = Generator{std::random_device{}()}) : eng(std::move(_eng)), dist() {}
    // construct from existing pre-defined engine
    explicit uniform_random_probability_generator(const Generator& _eng)
        : eng(_eng), dist() {}
    // generate next random value in distribution (equivalent to next() in above code)
    result_type operator()() { return dist(eng); }
    // will always yield 0.0 for this class type
    constexpr result_type min() const { return dist.min(); }
    // will always yield 1.0 for this class type
    constexpr result_type max() const { return dist.max(); }
    // resets internal state such that next call to operator() 
    // does not rely on previous call
    void reset_distribution_state() { dist.reset(); }
private:
    generator_type eng;
    distribution_type dist;
};

此外,uniform_random_probability_generator<> urpg; double next_prob = urpg(); 可以使用不同的uniform_random_probability_generator类型作为模板参数,只要此类型符合UniformRandomBitGenerator的要求即可。例如,如果出于任何原因需要使用Generator而不是std::knuth_b,那么您可以按以下方式执行此操作:

std::mt19937

答案 1 :(得分:2)

您可以创建一个包含随机数生成器作为私有成员变量(如std::mt19937)的类,并在构造函数中对其进行种子设定。你的next函数可以调用存储的生成器来获取下一个值(当然应用你想要的任何分布)。

这不是很复杂,所以我担心我错过了你问题的真正的点。