我正在尝试使用特定范围内的随机数初始化整数的特征向量。到目前为止,我的方法一直是创建一个函子并对其进行调用,但是从某种意义上来说,这是有问题的,因为我需要以一种不会每次都对其进行初始化的方式来初始化随机生成。
做到这一点的“最佳”方法是什么?速度明智。
到目前为止,我对函子的代码是:
std::mt19937 rd(time(0));
std::default_random_engine gen(rd());
template<typename Scalar>
struct RandomRange {
RandomRange(const Scalar& low, const Scalar& high) : m_low(low), m_high(high) {}
const Scalar operator()(const Scalar& high) const {
std::uniform_int_distribution<> dis(m_low, m_high);
return dis(gen); }
Scalar m_low, m_high;
};
我用它来称呼它
VectorXi testVec = VectorXi(10).unaryExpr(RandomRange<int>(5,100));
一个附带的问题是,在何处放置这样的定义合适?一般来说,我对c ++还是比较陌生,但是我想它应该放在头文件中,但是不确定如何将其与随机数生成器的初始化一起使用。
最诚挚的问候!
答案 0 :(得分:2)
首先,用一个梅森捻线机初始化(播种)default_random_engine
并没有任何意义。如果简单的随机引擎足够好,请直接用time(0)
或任何您喜欢的种子进行播种。如果您需要更长的真正独立的伪随机数序列,请直接将mt19937
对象传递给您的分布。
此外,您没有使用high
的{{1}}参数,因此实际上应该使用operator()
。另外,您可以使NullaryExpr
成为成员变量,并且可能最好将对生成器的引用存储起来,而不是使其成为全局变量:
dis
并这样称呼:
template<typename Scalar>
struct RandomRange {
RandomRange(const Scalar& low, const Scalar& high,
std::default_random_engine &gen) : dis(low, high), gen(gen) {}
const Scalar operator()() const { return dis(gen); }
mutable std::uniform_int_distribution<> dis;
std::default_random_engine &gen;
};
或
std::default_random_engine gen(time(0));
Eigen::VectorXi testVec = Eigen::VectorXi::NullaryExpr(10,RandomRange<int>(5,100, gen));
使用C ++ 11,您还可以只在本地定义您的发行版,并使用lambda表达式进行调用:
std::default_random_engine gen(time(0));
RandomRange<int> uniform(5,100, gen)
Eigen::VectorXi testVec = Eigen::VectorXi::NullaryExpr(10, uniform);
或
std::default_random_engine gen(time(0));
std::uniform_int_distribution<> dis(5,100);
Eigen::VectorXi testVec = Eigen::VectorXi::NullaryExpr(10,[&](){ return dis(gen); });
或
std::default_random_engine gen(time(0));
std::uniform_int_distribution<> dis(5,100);
auto uni = [&](){ return dis(gen); };
Eigen::VectorXi testVec = Eigen::VectorXi::NullaryExpr(10,uni);
一些Godbolt编译示例:https://godbolt.org/z/uG0j__
除非您发现这是一个瓶颈,否则我不会太在意哪种变体的性能最高(通过适当的优化,它们应该都等效),但是请使用最容易阅读和维护的变体代码库。