我试图用特定范围内的随机数初始化整数的特征向量。到目前为止,我的方法是创建一个仿函数并调用它,但是在某种意义上我需要以每次都不会重新初始化的方式初始化随机生成。
这样做的“最好”方式是什么?速度明智的。
到目前为止,我的仿函数代码是:
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 ++很新,但我想它应该在头文件中,但我不确定它如何与随机数生成器的初始化一起工作。
最好的祝福!
首先,用一个Mersenne-twister初始化(播种)default_random_engine
并没有多大意义。如果简单随机引擎足够好,可以用time(0)
或任何你喜欢的方式直接播种。如果您需要更长的真正独立的伪随机数序列,请直接将mt19937
对象传递给您的分布。
另外,你没有使用你的high
的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));
要么
std::default_random_engine gen(time(0));
RandomRange<int> uniform(5,100, gen)
Eigen::VectorXi testVec = Eigen::VectorXi::NullaryExpr(10, uniform);
使用C ++ 11,您还可以在本地定义分发并使用lambda表达式调用它:
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);
要么
std::default_random_engine gen(time(0));
Eigen::VectorXi testVec = Eigen::VectorXi::NullaryExpr(10,[&gen](){
std::uniform_int_distribution<> dis(5,100);
return dis(gen);
});
一些godbolt汇编示例:https://godbolt.org/z/uG0j__
除非你发现这是一个瓶颈,否则我不会太早关心什么变体是最有效的(通过适当的优化它们应该都是等价的),但是使用最容易在代码库中读取和维护的变体。