2

I have a function that calls srand and rand like this:

void foo() {
   int seed = some_operation();
   std::srand(seed);
   int value = std::rand();
   // Do something with random value
}

However, I don't want to change the global state of rand. Whats the easiest way to get a random number then?

Requirements:

  • random number must be deterministic based on seed
  • C++11 is fine
  • foo should be thread safe
  • the global state of rand should not be modified

Edit:

There is a stackoverflow question asking how to generate random numbers. The accepted answer however shows how to generate truly unique random numbers, using a slow std::random_device. I just needed a simple generator using a fixed seed instead.

Community
  • 1
  • 1
Jan Rüegg
  • 9,587
  • 8
  • 63
  • 105
  • 2
    possible duplicate of [Best way to generate random numbers using c++11 random library](http://stackoverflow.com/questions/19665818/best-way-to-generate-random-numbers-using-c11-random-library) – eerorika May 27 '15 at 14:09
  • Also [Random number generation in C++11 , how to generate , how do they work?](http://stackoverflow.com/q/7114043) – AliciaBytes May 27 '15 at 14:10

3 Answers3

4

C++11 is fine

Then use the new pseudorandom number library:

#include <random>

int foo() {
    int seed = some_operation();
    std::minstd_rand rand(seed);
    int value = rand();
    // Do something with random value
}

minstd_rand is a simple linear congruential engine, similar to that typically used by std::rand(), but with its state encapsulated in a class. Other engines are available, if you need a higher quality pseudorandom sequence. The Mersenne Twister, std::mt19937, is usually a good choice if you don't have specific requirements.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • @Brahim: To protect what? The engine is a local variable, so can only be accessed by the thread that's calling the function. – Mike Seymour May 27 '15 at 14:21
  • You are right. I just thought that the library functon's thread-safety may be undefined. – Brahim May 27 '15 at 14:24
2

<random> defines a number of PRNG classes that you can use, which do not use global states.

For example, using a default Mersenne Twister, std::mt19937:

#include <iostream>
#include <random>

int main() {
  int seed = 1234;
  std::mt19937 rng(seed);
  std::cout << "Random number: " << rng() << std::endl;
}
Frxstrem
  • 38,761
  • 9
  • 79
  • 119
1

One approach is to provide your own implementation, with its own seed data. A template for doing that is provided in the manpage for rand().

static unsigned long next = 1;

/* RAND_MAX assumed to be 32767 */
int myrand(void) {
    next = next * 1103515245 + 12345;
    return((unsigned)(next/65536) % 32768);
}

void mysrand(unsigned seed) {
    next = seed;
}
Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173
  • He asked for a solution with no global state, and you post an answer with global state. – DanielKO May 27 '15 at 16:47
  • 1
    @DanielKO: Actually, he said he didn't want to change *the* global state of `rand()`, which this does not. I get your point, however, and was kind of expecting that someone could modify this to manage the state in a way that suited their purposes -- for example if they wanted one seed per thread, that would require custom logic which isn't addressed in any of the answers. – Brent Bradburn May 27 '15 at 17:06
  • Note: The above code was copied verbatim from the man page. It is really only an example of how you might generate a predictable random number sequence in a very portable way (and with custom state data). Approaches using `` are likely better if you are targeting C++11 specifically. The code, as written, is not thread-safe. To achieve thread-safety you need to manage the state variable `next` in a way that matches your thread safety strategy. – Brent Bradburn May 27 '15 at 23:39