Lesson 78 +10 XP

Random Numbers

Random Numbers

Random numbers drive games, dice, and quizzes. Modern C++ gives you a clean way to produce them with the <random> header.

The old rand() has problems

The classic C function std::rand() is short and simple, but it is a weak generator and its range is awkward to shape. LearnCpp 8.13 and 8.14 recommend the modern <random> library instead.

A generator and a distribution

Random numbers come in two parts: a generator that produces a stream of numbers, and a distribution that shapes them into the range you want.

#include <iostream>
#include <random>
using namespace std;

int main() {
  mt19937 gen;                              // the generator
  uniform_int_distribution<int> dice(1, 6); // whole numbers 1..6
  for (int i = 0; i < 3; i++) {
    cout << dice(gen) << " ";
  }
  return 0;
}
  • mt19937 is the Mersenne Twister generator.
  • uniform_int_distribution<int> dice(1, 6) gives every integer from 1 to 6 the same chance.
  • dice(gen) hands back the next random value.

Seeding

Without a seed, the generator restarts at the same place each run and produces the same numbers. Seed it with something that changes, like the clock, so each run differs.

#include <iostream>
#include <random>
using namespace std;

int main() {
  mt19937 gen(time(NULL));                  // seed with the current time
  uniform_int_distribution<int> d(1, 100);
  cout << d(gen) << endl;
  return 0;
}

The seed is the starting point of the sequence. Different seeds give different sequences, which is why real applications seed once.

TL;DR

  • Modern random numbers come from the <random> header.
  • A generator makes the numbers; a distribution shapes the range.
  • mt19937 plus uniform_int_distribution is the go-to pair.
  • Seed the generator so different runs give different results.