使用特定范围内的随机数初始化特征矩阵或向量的有效方法?

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__

除非你发现这是一个瓶颈,否则我不会太早关心哪种变体性能最好(经过适当的优化,它们应该都是等效的),但使用最容易阅读和维护的变体在您的代码库中。