播种独立的位引擎,提升多精度

问题描述

我有一个简单的拒绝采样应用程序,该应用程序包装在一个类中,并在外部用作下面的虚拟示例所示。我能够将this帖子改编为boost :: multiprecision用例。但是,我不确定如何适当地植入generator的种子,并且找不到等效的random_device来增强。

以下代码“有效”,但是如果快速连续运行多次,您将获得我不想要的相同随机数。是否有比time(NULL)更敏感的东西?

#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/random.hpp>

using namespace boost::multiprecision; // used only for SO post
using namespace boost::random;

typedef independent_bits_engine<boost::mt19937,std::numeric_limits<cpp_dec_float_50>::digits,cpp_int> generator;


generator &gen()
{
  thread_local static generator genny(time(NULL));
  return genny;  
}

class dummy {
    public:
        dummy() = default;
        cpp_dec_float_50 rejectionSample() {
           uniform_real_distribution<cpp_dec_float_50> ur(0,1);
           cpp_dec_float_50 x = ur(gen());
           while (x > 0.1) 
               x = ur(gen());
           return x;
        }
};



int main()
{
    std::cout << std::setprecision(std::numeric_limits<cpp_dec_float_50>::digits10) << std::showpoint;

    dummy d;
    int nToGet = 5;
    for (int i = 0; i < nToGet; ++i) 
        std::cout << d.rejectionSample() << std::endl;
}

解决方法

这有效:

#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <random>
#include <boost/random.hpp>

using namespace boost::multiprecision;

typedef boost::random::independent_bits_engine<boost::mt19937,std::numeric_limits<cpp_dec_float_50>::digits,cpp_int> generator;

class dummy {
public:
    dummy()
    {
        ur_ = boost::random::uniform_real_distribution<cpp_dec_float_50>(0,1);
        std::random_device rd;
        gen_ = generator(rd());
        ur_(gen_);
    }

    cpp_dec_float_50 rejectionSample() {
        cpp_dec_float_50 x = ur_(gen_);
        while (x > 0.1)
        {
            x = ur_(gen_);
        }
        return x;
    }
private:
    boost::random::uniform_real_distribution<cpp_dec_float_50> ur_;
    generator gen_;
};



int main()
{
    std::cout << std::setprecision(std::numeric_limits<cpp_dec_float_50>::digits10) << std::showpoint;
    
    dummy d;
    int nToGet = 50;
    for (int i = 0; i < nToGet; ++i) {
        std::cout << d.rejectionSample() << std::endl;
    }
}

所以您的误解是:

  • 您在每次调用时都向uniform_real_distribution调用构造函数。本身并没有错,但是很昂贵。
  • 您在每次通话时都使用time(NULL)重新播种生成器。那真的很糟糕;这样一来,您甚至没有真正得到伪随机序列;您使用的是非递减时钟来生成生成器的种子,并且仅使用出现的第一个值。
  • 由于您对gen()有类似调用的语法,因此您似乎对发行版本的语法感到困惑。您正在将可通话对象传递给uniform_real_distribution
  • 您不应再将time(NULL)用作种子生成器;我们有更好的rdseed汇编指令。这就是std::random_device所称的。

最后,uniform_real_distribution不会在内部进行拒绝采样吗?那为什么要这么做呢?

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...