3

I'm using C++11's random library for producing deterministic random values, I need to restrict the output to various ranges and naturally used std::uniform_int_distribution but much to my dismay the specification gives library implementations too much freedom and output differs between i.e. X86-64 Linux and X86 Windows 7.

Is there any option besides implementing my own distribution to ensure that the output is deterministic regardless of library implementation?

Niall
  • 30,036
  • 10
  • 99
  • 142
bsdunx
  • 137
  • 7
  • 2
    Which randon number engine are you using? – jbgs Sep 29 '14 at 01:33
  • @jbgs I've tested the output of various random engines and they are indeed working as advertised across various STL implementations. – bsdunx Sep 29 '14 at 01:45

2 Answers2

2

Is there any option besides implementing my own distribution to ensure that the output is deterministic regardless of library implementation?

There is no option besides implementing your own distribution to ensure that the output is deterministic regardless of library implementation. While engines are deterministic, distributions are not.

Typical implementations for uniform_int_distribution will involve "rejection" algorithms which will repeatedly get a number from a URNG and if that result is not in the desired range, throw it away and try again. Variations on that theme will optimize that algorithm by folding out of range values into in-range values so as to minimize rejections without biasing the acceptance range, as the simplistic offset + lcg() % range algorithm does.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
1

At least if an LCG is good enough for your purpose, the std::linear_congruential_engine instantiated with some fixed constants your application provides should produce deterministic output.

typedef uint64_t number;
constexpr number a {1};
constexpr number c {2};
constexpr number m {3};
constexpr number seed {0};
std::linear_congruential_engine<number, a, c, m> lcg {seed};
std::uniform_int_distribution<number> dist {0, 1000};
for (int i = 0; i < 10; ++i)
  std::cout << dist(lcg) << std::endl;

Note that I've intentionally picked silly values for a, c and m so not to take any side in the debate about what would make a good set of parameters.

5gon12eder
  • 24,280
  • 5
  • 45
  • 92
  • LCG is one of the engines I have tested against, the PRNG itself is not the issue at hand, the distribution is where I am getting different outputs. – bsdunx Sep 29 '14 at 01:57
  • 1
    Oh, okay. It might be easiest to use `offset + lcg() % range` in that case. Lucky you only want uniform integer distributions. – 5gon12eder Sep 29 '14 at 02:05
  • Thanks for your comment, that was where I was going to be heading. At this point my primary concern is introducing bias, but hey it should work good enough for now and be trivial to replace at a later date. – bsdunx Sep 29 '14 at 02:19