繁体   English   中英

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

[英]C++ OOP: how to create a random number generator object?

所以这个问题有点翻译。 我是C ++的新手,正在查看类文档。 但是,似乎通过文档很难找到我的问题的答案。

我有用于在C ++中生成0到1之间的随机数的代码:(从此处获取 ,因为浮点数的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';
}

接下来,我想创建一个具有如下API的类或结构或某种东西(不是真正的OOP家伙):

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;
}

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

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] 

另外,要解决为什么您发布的类无法编译的问题,该类中的错误是您尝试使用std::mersenne_twister_engine实例初始化std::mt19937_64类型对象( randomGenerator ),但是它们本质上是不同的类型。 相反,您需要做

randomGenerator = std::mt19937_64(randomDevice());

MyRNG构造函数中,或者像上面的示例一样通过初始化列表进行构造。


正如评论中指出的那样,对此更合适的c ++式实现是重载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可以使用其他Generator类型作为模板参数,只要该类型满足UniformRandomBitGenerator的要求UniformRandomBitGenerator 例如,如果出于任何原因需要使用std::knuth_b而不是std::mt19937则可以执行以下操作:

uniform_random_probability_generator<double, std::knuth_b> urpg_kb;
double next_prob = urpg_kb();

您可以创建一个将随机数生成器作为私有成员变量保存的类(例如std::mt19937 ),并将其std::mt19937构造函数中。 您的next函数可以仅调用存储的生成器来获取下一个值(当然可以应用您想要的任何分布(如果有))。

这不是很复杂,所以恐怕我错过了您问题的实质

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM