boost::multiprecision 具有固定种子和可变精度的随机数
boost::multiprecision random number with fixed seed and variable precision
在 rng 中使用固定种子时,当精度发生变化时,结果无法重现。也就是说,如果更改模板参数 cpp_dec_float<xxx>
并运行以下代码,则会看到不同的输出(对于精度的每次更改)。
#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <random>
#include <boost/random.hpp>
typedef boost::multiprecision::cpp_dec_float<350> mp_backend; // <--- change me
typedef boost::multiprecision::number<mp_backend, boost::multiprecision::et_off> big_float;
typedef boost::random::independent_bits_engine<boost::mt19937, std::numeric_limits<big_float>::digits, boost::multiprecision::cpp_int> generator;
int main()
{
std::cout << std::setprecision(std::numeric_limits<big_float>::digits10) << std::showpoint;
auto ur = boost::random::uniform_real_distribution<big_float>(big_float(0), big_float(1));
generator gen = generator(42); // fixed seed
std::cout << ur(gen) << std::endl;
return 0;
}
我想似乎是合理的。但是我如何做到这一点,以便对于 n
位精度,固定种子将产生一个数字 x
相当于 n
位内的 y
其中 y
定义为 n+1
位?例如
x = 0.213099234 // n = 9
y = 0.2130992347 // n = 10
...
这些分布的工作方式是将随机位移动到浮点数的尾数中。如果更改精度,每次调用都会消耗更多这些位,因此会得到不同的随机序列。
如果不编写自己的 uniform_real_distribution
,我认为您无法实现目标。您可能需要两个整数 RNG,一个填充最高有效位,另一个填充最低有效位。
要添加到出色的@user14717 答案中,以获得可重现的结果,您必须:
使用宽(比输出尾数+1 宽)随机位生成器。比方说,您需要尾数不超过 128 位的 MP 双精度数,然后使用生成 128 位输出的位生成器。在内部,它可能是一些标准的 RNG,例如将单词链接在一起以达到所需宽度的梅森扭曲器。
您拥有 uniform_real_distribution,它将这 128 位转换为尾数
最后,丢弃 128 位包中的其余位。
使用这种方法可以保证您将获得相同的实际输出,唯一不同的是精度。
在 rng 中使用固定种子时,当精度发生变化时,结果无法重现。也就是说,如果更改模板参数 cpp_dec_float<xxx>
并运行以下代码,则会看到不同的输出(对于精度的每次更改)。
#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <random>
#include <boost/random.hpp>
typedef boost::multiprecision::cpp_dec_float<350> mp_backend; // <--- change me
typedef boost::multiprecision::number<mp_backend, boost::multiprecision::et_off> big_float;
typedef boost::random::independent_bits_engine<boost::mt19937, std::numeric_limits<big_float>::digits, boost::multiprecision::cpp_int> generator;
int main()
{
std::cout << std::setprecision(std::numeric_limits<big_float>::digits10) << std::showpoint;
auto ur = boost::random::uniform_real_distribution<big_float>(big_float(0), big_float(1));
generator gen = generator(42); // fixed seed
std::cout << ur(gen) << std::endl;
return 0;
}
我想似乎是合理的。但是我如何做到这一点,以便对于 n
位精度,固定种子将产生一个数字 x
相当于 n
位内的 y
其中 y
定义为 n+1
位?例如
x = 0.213099234 // n = 9
y = 0.2130992347 // n = 10
...
这些分布的工作方式是将随机位移动到浮点数的尾数中。如果更改精度,每次调用都会消耗更多这些位,因此会得到不同的随机序列。
如果不编写自己的 uniform_real_distribution
,我认为您无法实现目标。您可能需要两个整数 RNG,一个填充最高有效位,另一个填充最低有效位。
要添加到出色的@user14717 答案中,以获得可重现的结果,您必须:
使用宽(比输出尾数+1 宽)随机位生成器。比方说,您需要尾数不超过 128 位的 MP 双精度数,然后使用生成 128 位输出的位生成器。在内部,它可能是一些标准的 RNG,例如将单词链接在一起以达到所需宽度的梅森扭曲器。
您拥有 uniform_real_distribution,它将这 128 位转换为尾数
最后,丢弃 128 位包中的其余位。
使用这种方法可以保证您将获得相同的实际输出,唯一不同的是精度。