I have a simple rejection sampling application which is wrapped in a class and used externally as the dummy example below shows. I was able to adapt this post to a boost::multiprecision use case. However I'm not sure how to appropriately seed the generator
and can't find any random_device
equivalent for boost.
The below code 'works', but if you run it multiple times in quick succession you will get the same random numbers which I don't want. Is there something more sensitive than 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;
}
This works:
#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;
}
}
So your misunderstandings are:
uniform_real_distribution
on every call. Not wrong per se, but expensive.time(NULL)
. That's really bad; you're not getting really even getting a pseudorandom sequence that way; you're using the non-decreasing clock to seed a generator and using only the first value that comes out.gen()
. You are passing a callable to uniform_real_distribution
.time(NULL)
for seeding generators anymore; we have the rdseed
assembly instruction which is much better. This is what is called by std::random_device
. Finally, doesn't uniform_real_distribution
do rejection sampling internally? So why do you need to do it?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.