std :: simuror_real_distribution再生相同的随机数

std::uniform_real_distribution regenerating same random number

本文关键字:随机数 distribution simuror real std 再生      更新时间:2023-10-16

在运行下面的代码时,arr的上半场等于后半部分。为什么?我什至尝试了各种种子,例如std::chrono::system_clock::now().time_since_epoch().count()。谢谢。

#include <algorithm>
#include <iostream>
#include <random>

template<typename DistributionType>
class Rng 
{
public:
        template<typename ...Args>
        Rng(Args&&... args) : dist(args...) { } 
        typename DistributionType::result_type operator()()
        {
                return dist(gen);
        }
private:
        std::default_random_engine gen;
        DistributionType dist;
};

class UniformRealRng : public Rng<std::uniform_real_distribution<double>>
{
public:
        UniformRealRng(const double a, const double b) : Rng(a, b) { } 
};
int main()
{
        constexpr int sz = 6;
        constexpr int k  = sz / 2;
        double arr[sz];
        UniformRealRng rng(0.0, 1.0);
        std::generate(arr, arr + k, rng);
        std::generate(arr + k, arr + sz, rng);
        for (int i = 0; i < sz; ++i)
        {
                std::cout << arr[i];
        }
        std::cout << "n";
}

std::generate按值乘以第三个参数,因此rng被复制。

为了安全起见,可以删除复制:

Rng(Rng&)             = delete;   
Rng& operator=(Rng&)  = delete;

您的答案实际上是正确的,但不能解决问题。它仅在错误(?)试图复制随机数生成器时才产生汇编错误。

事实证明,通过使用std::reference_wrapper库功能,可以使代码在语义上正确。

    std::generate(arr, arr + k, std::ref(rng));
    std::generate(arr + k, arr + sz, std::ref(rng));

通过这种方式,您基本上是通过参考强迫通过参数。幸运的是参考包装器超载operator(),因此可以用于发电机,而无需任何其他代码。

完成代码:

#include <algorithm>
#include <iostream>
#include <random>
#include <functional> //ref
template<typename DistributionType>
class Rng 
{
public:
        template<typename ...Args>
        Rng(Args&&... args) : dist(args...) { } 
//      Rng(Rng&)             = delete;  // this is not needed for it to work 
//      Rng& operator=(Rng&)  = delete;  // you MAY want to copy the generator
        typename DistributionType::result_type operator()()
        {
                return dist(gen);
        }
private:
        std::default_random_engine gen;
        DistributionType dist;
};

class UniformRealRng : public Rng<std::uniform_real_distribution<double>>
{
public:
        UniformRealRng(const double a, const double b) : Rng(a, b) { } 
};
int main()
{
        constexpr int sz = 6;
        constexpr int k  = sz / 2;
        double arr[sz];
        UniformRealRng rng(0.0, 1.0);
        std::generate(arr, arr + k, std::ref(rng));
        std::generate(arr + k, arr + sz, std::ref(rng));
        for (int i = 0; i < sz; ++i)
        {
                std::cout << arr[i];
        }
        std::cout << "n";
}