简体   繁体   English

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

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

So this question is sort of one of translation. 所以这个问题有点翻译。 I am new to C++, and was looking through the class documentation. 我是C ++的新手,正在查看类文档。 However, it looks like finding the answer to my question is a bit hard via the documentation. 但是,似乎通过文档很难找到我的问题的答案。

I have code for generating a random number between 0 and 1 in C++: (obtained from here , since the rand() function solution for floats is integer based) 我有用于在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';
}

Next, I would like to create a class or struct or something (not really an OOP guy) that has an API like: 接下来,我想创建一个具有如下API的类或结构或某种东西(不是真正的OOP家伙):

float x = my_RandomNumberGenerator.next();

In python, I might write something like: 在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())

How would I implement this in C++? 我将如何在C ++中实现呢?

update Here is what I have so far (it does not work... or compile...but there seems to be some strangeness in the way things are initialized in my template code that I got from the reference site that I don't understand): 更新这是我到目前为止所拥有的(它不起作用...或编译...但是在从参考站点获得的我的模板代码中初始化事物的方式似乎有些陌生了解):

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

Seems like you just need some form of probability generation class, see below for a basic implementation which meets your question requirements: 似乎您只需要某种形式的概率生成类,请参阅下面的满足您问题要求的基本实现:

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

Then you can use this simply via: 然后,您可以通过以下方式简单地使用它:

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

Or if you want random float s instead (as part of your question seems to imply): 或者,如果您要使用随机float代替(作为您的问题的一部分似乎暗示):

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

Also, to address why the class you posted isn't compiling, the error in your class is that you try to initialise a std::mt19937_64 type object ( randomGenerator ) with a std::mersenne_twister_engine instance but they are fundamentally different types. 另外,要解决为什么您发布的类无法编译的问题,该类中的错误是您尝试使用std::mersenne_twister_engine实例初始化std::mt19937_64类型对象( randomGenerator ),但是它们本质上是不同的类型。 Instead you would need to do 相反,您需要做

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

in MyRNG constructor, or construct via initialisation list as I have done in the example above. MyRNG构造函数中,或者像上面的示例一样通过初始化列表进行构造。


As pointed out in the comments, a more suitable c++-esque implementation of this is to overload operator() instead of creating a next() method. 正如评论中指出的那样,对此更合适的c ++式实现是重载operator()而不是创建next()方法。 See below for a better implementation of the above class, 请参阅下文,以更好地实现上述类,

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

Then you can use this similarly to the first class in this answer, 然后,您可以像在此答案中的第一堂课一样使用它,

uniform_random_probability_generator<> urpg;
double next_prob = urpg();

Additionally, uniform_random_probability_generator can use a different Generator type as a template parameter so long as this type meets the requirements of UniformRandomBitGenerator . 此外, uniform_random_probability_generator可以使用其他Generator类型作为模板参数,只要该类型满足UniformRandomBitGenerator的要求UniformRandomBitGenerator For example, if for any reason you needed to use std::knuth_b instead of std::mt19937 then you can do so as follows: 例如,如果出于任何原因需要使用std::knuth_b而不是std::mt19937则可以执行以下操作:

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

You can create a class that holds a random number generator as a private member variable (like std::mt19937 ) and seeds it in the constructor. 您可以创建一个将随机数生成器作为私有成员变量保存的类(例如std::mt19937 ),并将其std::mt19937构造函数中。 Your next function could just invoke the stored generator to get the next value (applying whatever distribution you want (if any) of course). 您的next函数可以仅调用存储的生成器来获取下一个值(当然可以应用您想要的任何分布(如果有))。

This is not very complicated, so I'm afraid I'm missing the real point of your question.. 这不是很复杂,所以恐怕我错过了您问题的实质

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

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