0

Consider the following C++ program that produces a sequence of 10 random numbers based on a seed value entered by the user:

#include <iostream>
#include <random>

int main()
{
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_int_distribution<int> dist(0, 10000);

    int seed;
    std::cout << "Enter seed: ";
    std::cin >> seed;
    mt.seed(seed);

    for (int i=0; i<10; ++i) {
        std::cout << dist(mt) << std::endl;
    }

    return 0;
}

When I run this program on my MacBook and enter seed value 12345, it produces the following sequence of random numbers:

$ bin/demo
Enter seed: 12345
4578
2177
3492
4094
4478
546
7709
3441
7483
6798

If I run the program again and enter the same seed value 12345 again then, as expected, I get the same sequence of random numbers:

$ bin/demo
Enter seed: 12345
4578
2177
3492
4094
4478
546
7709
3441
7483
6798

When I run the program for the third time and enter a different seed value 11111 then, as expected, I get a different sequence of random numbers:

Enter seed: 11111
8996
3705
2111
8694
2740
5823
5557
5935
3417
9226

So far, so good: everything is as expected.

Now I compile the exact same program on a different operating system, namely Ubunty 18.04 running in AWS.

Now when I enter the exact seem seed value as before (12345) I get a different sequence of random numbers than on the MacBook:

$ bin/demo
Enter seed: 12345
9297
8902
3164
1307
1839
397
2045
8265
5677
5321

My question is: how can I write a portable C++ program that for a fixed given seed value always produces the same sequence of random numbers, across compilers and operating systems.

I need this to make a Monte Carlo simulation reproducible (by setting a seed value) across different compilers and operating systems.

Just in case it matters: I happen to be using the Clang C++14 compiler (but I want the same random number sequence to be produced by other compilers).

Bruno Rijsman
  • 3,715
  • 4
  • 31
  • 61

1 Answers1

5

The difference lies in the fact that uniform_int_distribution is implemented differently in different implementations of the C++ standard library. Note that it's not the "compiler" or the "operating system" that decides which algorithm is used. In fact, C++ distribution classes, such as uniform_int_distribution, have no standard implementation. See also this question.

On the other hand, random engines such as mt19937 do have a guaranteed implementation; they will return the same pseudorandom numbers for the same seed in all compliant C++ library implementations. (The exception is default_random_engine.) You can see this for yourself by replacing dist(mt) with mt() in the code you give in your question. See also this question.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
  • Yes, exactly this. I ended up using operator() provided by mt19937 to get my random number. That turned out to produce the exact same sequence number of random numbers on my MacBook vs an AWS instance. – Bruno Rijsman Apr 08 '20 at 14:49