Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use <random> to replace rand()?

Tags:

c++

random

c++11

C++11 introduced the header <random> with declarations for random number engines and random distributions. That's great - time to replace those uses of rand() which is often problematic in various ways. However, it seems far from obvious how to replace

srand(n); // ... int r = rand(); 

Based on the declarations it seems a uniform distribution can be built something like this:

std::default_random_engine engine; engine.seed(n); std::uniform_int_distribution<> distribution; auto rand = [&](){ return distribution(engine); } 

This approach seems rather involved and is surely something I won't remember unlike the use of srand() and rand(). I'm aware of N4531 but even that still seems to be quite involved.

Is there a reasonably simple way to replace srand() and rand()?

like image 630
Dietmar Kühl Avatar asked Oct 03 '15 21:10

Dietmar Kühl


People also ask

Why is rand () giving me the same number?

The RAND function in stand-alone applications generates the same numbers each time you run your application because the uniform random number generator that RAND uses is initialized to same state when the application is loaded.

What is the difference between Rand and random?

There is no difference between RAND and RANDOM. Both functions are included to ensure portability of existing code that references one or both of them. The intrinsic functions RANDOM_NUMBER and RANDOM_SEED provide the same functionality. You can use SRAND to restart the pseudorandom number generator used by RAND.


2 Answers

Is there a reasonably simple way to replace srand() and rand()?

Full disclosure: I don't like rand(). It's bad, and it's very easily abused.

The C++11 random library fills in a void that has been lacking for a long, long time. The problem with high quality random libraries is that they're oftentimes hard to use. The C++11 <random> library represents a huge step forward in this regard. A few lines of code and I have a very nice generator that behaves very nicely and that easily generates random variates from many different distributions.


Given the above, my answer to you is a bit heretical. If rand() is good enough for your needs, use it. As bad as rand() is (and it is bad), removing it would represent a huge break with the C language. Just make sure that the badness of rand() truly is good enough for your needs.

C++14 didn't deprecate rand(); it only deprecated functions in the C++ library that use rand(). While C++17 might deprecate rand(), it won't delete it. That means you have several more years before rand() disappears. The odds are high that you will have retired or switched to a different language by the time the C++ committee finally does delete rand() from the C++ standard library.

I'm creating random inputs to benchmark different implementations of std::sort() using something along the lines of std::vector<int> v(size); std::generate(v.begin(), v.end(), std::rand);

You don't need a cryptographically secure PRNG for that. You don't even need Mersenne Twister. In this particular case, rand() probably is good enough for your needs.


Update
There is a nice simple replacement for rand() and srand() in the C++11 random library: std::minstd_rand.

#include <random> #include <iostream>  int main () {     std:: minstd_rand simple_rand;      // Use simple_rand.seed() instead of srand():     simple_rand.seed(42);      // Use simple_rand() instead of rand():     for (int ii = 0; ii < 10; ++ii)     {         std::cout << simple_rand() << '\n';     } } 

The function std::minstd_rand::operator()() returns a std::uint_fast32_t. However, the algorithm restricts the result to between 1 and 231-2, inclusive. This means the result will always convert safely to a std::int_fast32_t (or to an int if int is at least 32 bits long).

like image 79
David Hammen Avatar answered Sep 29 '22 18:09

David Hammen


How about randutils by Melissa O'Neill of pcg-random.org?

From the introductory blog post:

randutils::mt19937_rng rng;  std::cout << "Greetings from Office #" << rng.uniform(1,17)           << " (where we think PI = "  << rng.uniform(3.1,3.2) << ")\n\n"           << "Our office morale is "   << rng.uniform('A','D') << " grade\n"; 
like image 33
jtbandes Avatar answered Sep 29 '22 18:09

jtbandes