Search code examples
randomboost-multiprecision

boost::multiprecision random number with fixed seed and variable precision


When using a fixed seed inside a rng, results are not reproducible when precision is varied. Namely, if one changes the template argument cpp_dec_float<xxx> and runs the following code, different outputs are seen (for each change in precision).

#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;
}

Seems reasonable I guess. But how do I make it so that for n digits of precision, a fixed seed will produce a number x which is equivalent to y within n digits where y is defined for n+1 digits? e.g.

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

Solution

  • To add to the excellent @user14717 answer, to get reproducible result, you would have to:

    1. Use wide (wider than output mantissa+1) random bits generator. Lets say, you need MP doubles with no more than 128bit mantissa, then use bits generator which produces 128bit output. Internally, it could be some standard RNG like mersenne twister chaining words together to achieve desired width.

    2. You own uniform_real_distribution, which converts this 128bits to mantissa

    3. And at the end, DISCARD the rest of the bits in the 128bits pack.

    Using this approach would guarantee you'll get the same real output, only difference being in precision.