使用特定范围内的随机数初始化特征矩阵或向量的有效方法?
Efficient way to initialize Eigen Matrix or Vector with random numbers from a specific range?
我正在尝试用特定范围内的随机数初始化整数的本征向量。到目前为止,我的方法是创建一个仿函数并调用它,但是从某种意义上说,它是有问题的,因为我需要以一种不会每次都重新初始化的方式初始化随机生成。
"the best" 这样做的方法是什么?速度方面。
到目前为止,我的仿函数代码是:
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++ 比较陌生,但我想它应该在头文件中,但我不确定它如何与随机数生成器的初始化一起工作。
此致!
首先,初始化(播种)一个 default_random_engine
与梅森扭曲的一个数字并没有真正意义。如果简单的随机引擎足够好,直接用 time(0)
或任何你喜欢的方式为它播种。如果您需要更长的真正独立的伪随机数序列,请直接将 mt19937
对象传递给您的分配。
此外,您没有使用 operator()
的 high
参数,因此您实际上应该使用 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__
除非你发现这是一个瓶颈,否则我不会太早关心哪种变体性能最好(经过适当的优化,它们应该都是等效的),但使用最容易阅读和维护的变体在您的代码库中。
我正在尝试用特定范围内的随机数初始化整数的本征向量。到目前为止,我的方法是创建一个仿函数并调用它,但是从某种意义上说,它是有问题的,因为我需要以一种不会每次都重新初始化的方式初始化随机生成。
"the best" 这样做的方法是什么?速度方面。
到目前为止,我的仿函数代码是:
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++ 比较陌生,但我想它应该在头文件中,但我不确定它如何与随机数生成器的初始化一起工作。
此致!
首先,初始化(播种)一个 default_random_engine
与梅森扭曲的一个数字并没有真正意义。如果简单的随机引擎足够好,直接用 time(0)
或任何你喜欢的方式为它播种。如果您需要更长的真正独立的伪随机数序列,请直接将 mt19937
对象传递给您的分配。
此外,您没有使用 operator()
的 high
参数,因此您实际上应该使用 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__
除非你发现这是一个瓶颈,否则我不会太早关心哪种变体性能最好(经过适当的优化,它们应该都是等效的),但使用最容易阅读和维护的变体在您的代码库中。