Random output differs from implementations

I tried this program with libstdc ++, libc ++ and dinkumware:

#include <iostream> #include <algorithm> #include <vector> #include <random> #include <functional> #include <limits> int main() { std::vector<int> v(10); std::mt19937 rand{0}; std::uniform_int_distribution<> dist( 1, 10 ); std::generate_n(v.begin(), v.size(), std::bind(dist, rand)); for (auto i : v) std::cout << i << " "; } 

Output:

 6 6 8 9 7 9 6 9 5 7 6 1 4 4 8 10 4 6 3 5 5 10 4 1 4 10 8 4 8 4 

The result is consistent for each run, but as you can see, they are different. Explain?

+5
source share
2 answers

For uniform_int_distribution<> no execution is required. [rand.dist.general] indicates that:

The algorithms for creating each of these distributions are determined by the implementation.

Everything that is indicated in [rand.dist.uni.int]:

In the distribution of random numbers uniform_int_distribution, random integers i , a <= i <= b produced, distributed in accordance with the constant discrete probability function P(i | a, b) = 1/(b βˆ’ a + 1) .

Each implementation is free to perform this distribution as desired. What you see, apparently, consists of three different realizations.

+7
source

To be clear: the random number generators themselves are indicated quite strongly - including input parameters and results. To be technical, what is indicated is the result of 10,000 th from the generator, built by default, but for any practical purpose, the coincidence of this result from the generator is at least reasonably close to the rule, otherwise it substantially guarantees that the generator works correctly. and its outputs will match any other similar generator for a given seed.

For example, a quick test:

 #include <random> #include <iostream> int main() { std::mt19937 r; for (int i=0; i<10000-2; i++) r(); for (int i=0; i<3; i++) std::cout << r() << "\n"; } 

... shows the same results with each (last) compiler, which is convenient for me:

 1211010839 4123659995 725333953 

The second of these three values ​​is the value required by the standard.

However, distribution templates give additional freedom. A uniform_int_distribution should uniformly map inputs to outputs, but there are different ways to do this, and there is no requirement on which of these methods to use.

If you really need to create a sequence of integers within a range that is not only evenly distributed but also consistent across implementations, you will probably have to implement your own distribution code. Doing it well is not as trivial as most people think. Maybe you should take a look at one of my previous answers for a working implementation, as well as some explanation and some test code.

+2
source

Source: https://habr.com/ru/post/1232126/


All Articles