具有固定种子和可变精度的 boost::multiprecision 随机数

Posted

技术标签:

【中文标题】具有固定种子和可变精度的 boost::multiprecision 随机数【英文标题】:boost::multiprecision random number with fixed seed and variable precision 【发布时间】:2020-08-18 03:57:24 【问题描述】:

在 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
...

【问题讨论】:

【参考方案1】:

要添加到出色的 @user14717 答案,以获得可重现的结果,您必须:

    使用宽(比输出尾数+1 宽)随机位生成器。可以说,您需要不超过 128 位尾数的 MP 双打,然后使用产生 128 位输出的位生成器。在内部,它可能是一些标准的 RNG,例如 mersenne twister,将单词链接在一起以达到所需的宽度。

    你拥有 uniform_real_distribution,它将这 128 位转换为尾数

    最后,丢弃 128 位包中的其余位。

使用这种方法可以保证您获得相同的实际输出,只是精度不同。

【讨论】:

【参考方案2】:

这些分布的工作方式是将随机位移入浮点数的尾数。如果更改精度,每次调用都会消耗更多这些位,因此会得到不同的随机序列。

如果不编写自己的 uniform_real_distribution,我认为您无法实现目标。您可能需要两个整数 RNG,一个填充最高有效位,另一个填充最低有效位。

【讨论】:

以上是关于具有固定种子和可变精度的 boost::multiprecision 随机数的主要内容,如果未能解决你的问题,请参考以下文章

boost::multi_index_container 带有 random_acces 和 hashed_unique

多索引表 boost::multi_index多索引容器

使 NSView 具有适合内容的固定宽度和可变高度

Java Swing:具有固定宽度和可变高度的垂直布局

SQL 数据库 数据类型 固定长度的字符串怎么定义

在固定区域中具有可变内容和控制按钮的表单