Skip to content
Why is a raven like a writing desk?

Thoughts both confusing and enlightening.

Why is a raven like a writing desk?

Thoughts both confusing and enlightening.

Rules for using <random>

elbeno, 8 April, 20153 June, 2025

These days, it’s easy to do the right thing.

Don’t do this:

  • Don’t use std::rand(). Ever.
  • Don’t use std::random_shuffle() to permute containers. (Too easy to misuse; can use std::rand() under the hood.)
  • Don’t use any kind of clock for a seed.
  • Don’t use mod (%) to get a random value into a range. It introduces bias.
  • Don’t use std::default_random_engine – it’s probably not the best choice and can vary by implementation.

Do this:

  • Use std::random_device() as a source of entropy. It should be the best randomness your OS can supply.
  • Use std::shuffle() to permute containers. Its interface doesn’t permit misuse like std::random_shuffle().
  • Use std::mt19937 (or std::mt19937_64) as an RNG engine. (Or consider PCG, but that’s not standard – yet.)
  • Seed the engine with as much seed data as it requires for its internal state (using its state_size member), otherwise you’re throwing away entropy. For std::mt19937 this is 624 32-bit values (not just a single 32-bit value). Use std::seed_seq to help with initialization.
  • RNG engines (particularly std::mt19937) can be expensive to initialize (and have large amounts of internal state), so don’t put them on the stack unnecessarily. Consider using thread_local.
  • Use std::uniform_int_distribution (and the other distributions) to get your random number into the required range. The distributions are carefully crafted to be unbiased (why you shouldn’t use %). Note that they work on closed (inclusive) ranges, not half-open ranges – otherwise the max value would be unreachable.

Wrong:

// init RNG
srand(time(NULL));

// get random number
int n = rand() % 100;

Right:

// init RNG
std::array<int, std::mt19937::state_size> seed_data;
std::random_device r;
std::generate_n(seed_data.data(), seed_data.size(), std::ref(r));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
std::mt19937 gen(seq);

// get random number
std::uniform_int_distribution dis(0,99);
int n = dis(gen);

Edit: Alternatively, Melissa O’Neill has produced randutils which wraps C++11 random number generation in a nice interface, and does the right thing. She knows what she’s talking about: her work on randomness is worth your time.

C++ Programming

Post navigation

Previous post
Next post

Related Posts

Exercising Ranges (part 5)

1 July, 20151 July, 2015

(Start at the beginning of the series if you want more context.) Generalising iota To pretty-print a reversible polynomial, we need to provide for reversibility of iota. So what is iota? It makes a range by repeatedly incrementing a value. What if instead of increment, we use an arbitrary function?…

Read More

Remember the Vasa! or, plus ça change, plus c’est la même chose

12 August, 201915 September, 2021

I’ve been programming in C++ for almost a quarter of a century now. I grew up, professionally, with C++, and in many ways, it grew up along with me. For someone who is used to C++, even used to recently-standardised C++, it’s hard not to feel apprehension when looking at…

Read More

Floating-point maths, constexpr style

13 October, 201515 October, 2015

(Start at the beginning of the series – and all the source can be found in my github repo) To ease into constexpr programming I decided to tackle some floating-point maths functions. Disclaimer: I’m not a mathematician and this code has not been rigorously tested for numeric stability or convergence…

Read More

Comments (5)

  1. Alan Wolfe says:
    8 April, 2015 at 11:55 am

    Hey Ben, is std::rand() the same as the older rand(), and that’s why we should avoid it due to being low quality and offering a low range of output values?

  2. elbeno says:
    8 April, 2015 at 1:18 pm

    Yes, it’s just the old LCG.

  3. Pingback: Don’t blink, or you’ll mess up the Mersenne Twister | Backworlds
  4. Pingback: Interesting C++ Tutorials | Declan Kelly
  5. Henry says:
    8 April, 2018 at 5:55 am

    It is worthing to write an input iterator instead of using std::array so that we can avoid extra memory usage.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

©2026 Why is a raven like a writing desk? | WordPress Theme by SuperbThemes