boost :: multiprecision случайное число с фиксированным начальным числом и переменной точностью

При использовании фиксированного посевного материала внутри диапазона, результаты не воспроизводятся при изменении точности. А именно, если изменить аргумент шаблона 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, которое эквивалентно y в пределах n цифр, где y определено для n+1 цифр? например

x = 0.213099234     // n = 9
y = 0.2130992347    // n = 10
...

person algae    schedule 18.08.2020    source источник


Ответы (2)


Чтобы добавить к отличному ответу @ user14717 и получить воспроизводимый результат, вам необходимо:

  1. Используйте широкий (шире, чем выходная мантисса + 1) генератор случайных битов. Допустим, вам нужны удвоения MP с мантиссой не более 128 бит, а затем используйте генератор бит, который производит 128-битный вывод. Внутри это может быть какой-нибудь стандартный ГСЧ, такой как mersenne twister, объединяющий слова в цепочку для достижения желаемой ширины.

  2. У вас есть uniform_real_distribution, которая преобразует эти 128 бит в мантиссу.

  3. И, в конце, ОТКАЗЫВАЙТЕСЬ от остальных битов в пакете 128 бит.

Использование этого подхода гарантирует, что вы получите тот же реальный результат, только разница будет в точности.

person Severin Pappadeux    schedule 18.08.2020

Принцип работы этих распределений заключается в сдвиге случайных битов в мантиссу числа с плавающей запятой. Если вы измените точность, вы потребляете больше этих бит при каждом вызове, поэтому вы получаете разные случайные последовательности.

Я не вижу возможности достичь своей цели без написания собственного uniform_real_distribution. Вероятно, вам понадобятся два целочисленных ГСЧ, один из которых заполняет наиболее значимые биты, а другой - наименее значимые.

person user14717    schedule 18.08.2020