生成T类型的随机数

问题描述 投票:0回答:3

我正在编写一个包含

list<T>
的程序,其中
T
int
double
。我想创建一个函数,使用标题
<random>
中的组件,生成
T
类型的数字。我找不到以
T
作为模板参数的分布。

该函数将用于调用

generate
函数:

generate(myList.begin(), myList.end(), RandomGenerator())

我该怎么做?

我尝试创建一个名为

RandomGenerator
的类并为其重载
operator()
。 当我尝试将参数传递给重载的
operator()
时,我收到错误。

函数调用,

Random(b)
是一个函数对象,带有
int
参数
b

generate(rList.begin(), rList.end(), Random(b)); 

用于重载

()
的代码,其中
n
是一种“虚拟”变量,用于仅告诉它是什么类型:

int operator()(int n)
{
    std::uniform_int_distribution<int> dist(1000, 2000);
    return dist(gen);
}

错误信息:

Error   2   error C2440: '<function-style-cast>' : cannot convert from 'int' to 'Random'    

Error   3   error C2780: 'void std::generate(_FwdIt,_FwdIt,_Fn0)' : expects 3 arguments - 2 provided    
c++ c++11
3个回答
3
投票

除了 Joey 的回答之外,以下内容应该与

std::generate
配合得很好。免责声明:我不擅长元编程,请指出任何错误或可能的改进。这是一个 C++11 解决方案,使用 C++14 会更短一些。

Coliru 现场演示

#include <algorithm>
#include <iostream>
#include <list>
#include <random>
#include <type_traits>

template<typename T,
         typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
class random_generator {
    using distribution_type = typename std::conditional<
            std::is_integral<T>::value,
            std::uniform_int_distribution<T>,
            std::uniform_real_distribution<T>
        >::type;

    std::default_random_engine engine;
    distribution_type distribution;

public:
    auto operator()() -> decltype(distribution(engine)) {
        return distribution(engine);
    }
};

template<typename Container, typename T = typename Container::value_type>
auto make_generator(Container const&) -> decltype(random_generator<T>()) {
    return random_generator<T>();
}

int main() {
    auto l = std::list<double>(10);

    std::generate(std::begin(l), std::end(l), make_generator(l));    

    for (auto i : l) {
        std::cout << i << " ";    
    }
}

3
投票

不是一个优雅的解决方案,但可以满足您的要求:(修改代码以便可以与生成一起使用)

template <typename Distribution>
class RandomGenerator
{
    using Type = typename Distribution::result_type;

    const Type getRandom(const Type& lower, const Type& upper) const
    {
        static std::default_random_engine generator;
        static Distribution distribution(lower, upper);

        return distribution(generator);
    }

public:
    RandomGenerator(const Type& lowerBound, const Type& upperBound) : _lowerBound(lowerBound), _upperBound(upperBound) { }

    const Type operator()() const
    {
        return getRandom(_lowerBound, _upperBound);
    }

private:
    Type _lowerBound;
    Type _upperBound;
};

int main()
{
    RandomGenerator<std::uniform_int_distribution<>> randomIntGenerator(1, 10);
    RandomGenerator<std::uniform_real_distribution<>> randomDoubleGenerator(0.0, 10.0);

    std::deque<int> intRandoms(10);
    std::generate(intRandoms.begin(), intRandoms.end(), randomIntGenerator);

    std::deque<double> doubleRandoms(5);
    std::generate(doubleRandoms.begin(), doubleRandoms.end(), randomDoubleGenerator);

    return 0;
}

当然,如果我们希望每次运行都有不同的数字,我们可以将 default_random_engine 的种子设置为类似 time(0) 的值,但我会忽略这个。


0
投票

这是我的尝试(警告:我只是写了它)。它支持

bool
和整数类型,但不支持
double
(尽管这很容易添加)。它对返回类型使用类型推导。

#include <iostream>
#include <random>
#include <cstdint>

template<typename PRNG>
class Random
{
public:
    Random(PRNG& prng) : m_prng(prng) {}

    operator bool() const {
        return (m_prng() & 1) != 0;
    }

    template<
        typename T,
        typename = typename std::enable_if_t<std::is_integral_v<T>>
    >
    operator T() const {
        return std::uniform_int_distribution<T>()(m_prng);
    }
private:
    PRNG& m_prng;

};


int main() {
    for (unsigned i = 0; i < 100; ++i) {
        std::mt19937_64 prng(i);
        bool x = Random(prng);
        uint8_t y = Random(prng);
        uint32_t z = Random(prng);
        std::cout << x << " " << int(y) << " " << z << std::endl;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.