Generating random numbers in C ++ using TR1 / dev / random (resistant to <1 seconds)

I would like to generate uniform random numbers in C ++ between 0 and 1 in a way that doesn't use the standard rand() and srand(time(NULL)) methods. The reason for this is that if I run the application more than once in one second of my watch, the seed will be exactly the same and produce the same result.

I do not want to rely on features of boost or OS / compiler. x86 can be assumed.

It seems like an alternative way to do this is to use TR1 (I don't have C ++ 11) and seeding with /dev/random some way?

I have it now, but it still uses time(NULL) as a seed, which will not work for 1 second:

 #include <iostream> #include <tr1/random> int main() { std::tr1::mt19937 eng; eng.seed(time(NULL)); std::tr1::uniform_int<int> unif(1, RAND_MAX); int u = unif(eng); std::cout << (float)u/RAND_MAX << std::endl; } 
+6
source share
3 answers

Posting on OP request:

This is still somewhat compiler specific, but will work with almost all x86 targeting compilers:

 #ifdef _WIN32 // Windows #define rdtsc __rdtsc #else // For everything else unsigned long long rdtsc(){ unsigned int lo,hi; __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); return ((unsigned long long)hi << 32) | lo; } #endif int main() { std::tr1::mt19937 eng; eng.seed( rdtsc() ); // Seed with rdtsc. std::tr1::uniform_int<int> unif(1, RAND_MAX); int u = unif(eng); std::cout << (float)u/RAND_MAX << std::endl; } 

The idea here is to seed your random number generator using the rdtsc loop rdtsc .

The reason this happens is because the rdtsc loop counter rdtsc at about the frequency (often the same) as the processor frequency. Thus, the chances of two calls to it returning the same value are extremely small, which makes it a great seed for RNG.

+7
source

TR1 in [tr.rand.device] specifies a random_device class that generates unsigned random_device from an implementation-specific source. Therefore, the following should work, although I have not compiled it myself:

 int main() { std::tr1::random_device dev_random; std::tr1::mt19937 eng(dev_random()); ... 

In TR1, passing dev_random directly without calling it works and initializes the state in a more random way, but in C ++ 11 you have to transfer the initial arguments to another class. Since argument invocation works in both libraries, I would do this for ease of maintenance if you don't have more complex requirements.

+4
source

Your problem is related to how you sow the random number generator. Obviously, sowing over time (NULL) will produce the same PRNG sequence for this second when sowing. This is the most common rand seed method, but unfortunately this is bad practice due to this very problem. Not only that, I read that this can lead to biased results.

Note that EVERY PRNG will produce the same result if you see the same values . So your problem is not with the generator, more for sowing.

I asked a question about sowing here just a few weeks ago and got a link to the next article, which you can also find useful. Good practice in (pseudo) random number generation for bioinformatics applications . See Section on sowing or warming up a generator.

rand () is not the best random number generator, but is suitable in many cases if it is correctly sown. If you need something better where the repetition sequence is very long, then there are some in this link. Or use TR1. Personally, I would go with more portable C ++ 03 code and avoid TR1.

Also consider Carry Multiply as an alternative PRNG algorithm.

+1
source

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


All Articles