9.5 — Random number generation

The ability to generate random numbers can be useful in certain kinds of programs, particularly in games, statistics modeling programs, and scientific simulations that need to model random events. Take games for example -- without random events, monsters would always attack you the same way, you’d always find the same treasure, the dungeon layout would never change, etc… and that would not make for a very good game.

So how do we generate random numbers? In real life, we often generate random results by doing things like flipping a coin, rolling a dice, or shuffling a deck of cards. These events involve so many physical variables (e.g. gravity, friction, air resistance, momentum, etc…) that they become almost impossible to predict or control, and produce results that are for all intents and purposes random.

However, computers aren’t designed to take advantage of physical variables -- your computer can’t toss a coin, throw a dice, or shuffle real cards. Computers live in a controlled electrical world where everything is binary (false or true) and there is no in-between. By their very nature, computers are designed to produce results that are as predictable as possible. When you tell the computer to calculate 2 + 2, you always want the answer to be 4. Not 3 or 5 on occasion.

Consequently, computers are generally incapable of generating random numbers. Instead, they must simulate randomness, which is most often done using pseudo-random number generators.

A pseudo-random number generator (PRNG) is a program that takes a starting number (called a seed), and performs mathematical operations on it to transform it into some other number that appears to be unrelated to the seed. It then takes that generated number and performs the same mathematical operation on it to transform it into a new number that appears unrelated to the number it was generated from. By continually applying the algorithm to the last generated number, it can generate a series of new numbers that will appear to be random if the algorithm is complex enough.

Best practice

You should only seed your random number generators once. Seeding them more than once will cause the results to be less random or not random at all.

It’s actually fairly easy to write a PRNG. Here’s a short program that generates 100 pseudo-random numbers:

The result of this program is:

23070   27857   22756   10839   27946
11613   30448   21987   22070   1001
27388   5999    5442    28789   13576
28411   10830   29441   21780   23687
5466    2957    19232   24595   22118
14873   5932    31135   28018   32421
14648   10539   23166   22833   12612
28343   7562    18877   32592   19011
13974   20553   9052    15311   9634
27861   7528    17243   27310   8033
28020   24807   1466    26605   4992
5235    30406   18041   3980    24063
15826   15109   24984   15755   23262
17809   2468    13079   19946   26141
1968    16035   5878    7337    23484
24623   13826   26933   1480    6075
11022   19393   1492    25927   30234
17485   23520   18643   5926    21209
2028    16991   3634    30565   2552
20971   23358   12785   25092   30583

Each number appears to be pretty random with respect to the previous one. As it turns out, our algorithm actually isn’t very good, for reasons we will discuss later. But it does effectively illustrate the principle of PRNG number generation.

Generating random numbers in C++

C (and by extension C++) comes with a built-in pseudo-random number generator. It is implemented as two separate functions that live in the cstdlib header:

std::srand() sets the initial seed value to a value that is passed in by the caller. std::srand() should only be called once at the beginning of your program. This is usually done at the top of main().

std::rand() generates the next random number in the sequence. That number will be a pseudo-random integer between 0 and RAND_MAX, a constant in cstdlib that is typically set to 32767.

Here’s a sample program using these functions:

Here’s the output of this program:

17421	8558	19487	1344	26934	
7796	28102	15201	17869	6911	
4981	417	12650	28759	20778	
31890	23714	29127	15819	29971	
1069	25403	24427	9087	24392	
15886	11466	15140	19801	14365	
18458	18935	1746	16672	22281	
16517	21847	27194	7163	13869	
5923	27598	13463	15757	4520	
15765	8582	23866	22389	29933	
31607	180	17757	23924	31079	
30105	23254	32726	11295	18712	
29087	2787	4862	6569	6310	
21221	28152	12539	5672	23344	
28895	31278	21786	7674	15329	
10307	16840	1645	15699	8401	
22972	20731	24749	32505	29409	
17906	11989	17051	32232	592	
17312	32714	18411	17112	15510	
8830	32592	25957	1269	6793

PRNG sequences and seeding

If you run the std::rand() sample program above multiple times, you will note that it prints the same result every time! This means that while each number in the sequence is seemingly random with regards to the previous ones, the entire sequence is not random at all! And that means our program ends up totally predictable (the same inputs lead to the same outputs every time). There are cases where this can be useful or even desired (e.g. you want a scientific simulation to be repeatable, or you’re trying to debug why your random dungeon generator crashes).

But often, this is not what is desired. If you’re writing a game of hi-lo (where the user has 10 tries to guess a number, and the computer tells them whether their guess is too high or too low), you don’t want the program picking the same numbers each time. So let’s take a deeper look at why this is happening, and how we can fix it.

Remember that each number in a PRNG sequence is generated from the previous number, in a deterministic way. Thus, given any starting seed number, PRNGs will always generate the same sequence of numbers from that seed as a result! We are getting the same sequence because our starting seed number is always 5323.

In order to make our entire sequence randomized, we need some way to pick a seed that’s not a fixed number. The first answer that probably comes to mind is that we need a random number! That’s a good thought, but if we need a random number to generate random numbers, then we’re in a catch-22. It turns out, we really don’t need our seed to be a random number -- we just need to pick something that changes each time the program is run. Then we can use our PRNG to generate a unique sequence of pseudo-random numbers from that seed.

The commonly accepted method for doing this is to enlist the system clock. Each time the user runs the program, the time will be different. If we use this time value as our seed, then our program will generate a different sequence of numbers each time it is run!

C comes with a function called std::time() that returns the number of seconds since midnight on Jan 1, 1970. To use it, we merely need to include the ctime header, and then initialize std::srand() with a call to std::time(nullptr). We haven’t covered nullptr yet, but it’s essentially the equivalent of 0 in this context.

Here’s the same program as above, using a call to time() as the seed:

Now our program will generate a different sequence of random numbers every time! Run it a couple of times and see for yourself.

Generating random numbers between two arbitrary values

Generally, we do not want random numbers between 0 and RAND_MAX -- we want numbers between two other values, which we’ll call min and max. For example, if we’re trying to simulate the user rolling a die, we want random numbers between 1 and 6 (pedantic grammar note: yes, die is the singular of dice).

Here’s a short function that converts the result of rand() into the range we want:

To simulate the roll of a die, we’d call getRandomNumber(1, 6). To pick a randomized digit, we’d call getRandomNumber(0, 9).

Optional reading: How does the previous function work?

The getRandomNumber() function may seem a little complicated, but it’s not too bad.

Let’s revisit our goal. The function rand() returns a number between 0 and RAND_MAX (inclusive). We want to somehow transform the result of rand() into a number between min and max (inclusive). This means that when we do our transformation, 0 should become min, and RAND_MAX should become max, with a uniform distribution of numbers in between.

We do that in five parts:

  1. We multiply our result from std::rand() by fraction. This converts the result of rand() to a floating point number between 0 (inclusive), and 1 (exclusive).

    If rand() returns a 0, then 0 * fraction is still 0. If rand() returns RAND_MAX, then RAND_MAX * fraction is RAND_MAX / (RAND_MAX + 1), which is slightly less than 1. Any other number returned by rand() will be evenly distributed between these two points.

  2. Next, we need to know how many numbers we can possibly return. In other words, how many numbers are between min (inclusive) and max (inclusive)?

    This is simply (max - min + 1). For example, if max = 8 and min = 5, (max - min + 1) = (8 - 5 + 1) = 4. There are 4 numbers between 5 and 8 (that is, 5, 6, 7, and 8).

  3. We multiply the prior two results together. If we had a floating point number between 0 (inclusive) and 1 (exclusive), and then we multiply by (max - min + 1), we now have a floating point number between 0 (inclusive) and (max - min + 1) (exclusive).
  4. We cast the previous result to an integer. This removes any fractional component, leaving us with an integer result between 0 (inclusive) and (max - min) (inclusive).
  5. Finally, we add min, which shifts our result to an integer between min (inclusive) and max (inclusive).

Optional reading: Why don’t we use the modulus operator (%) in the previous function?

One of the most common questions readers have submitted is why we use division in the above function instead of modulus (%). The short answer is that the modulus method tends to be biased in favor of low numbers.

Let’s consider what would happen if the above function looked like this instead:

Seems similar, right? Let’s explore where this goes wrong. To simplify the example, let’s say that rand() always returns a random number between 0 and 9 (inclusive). For our sample case, we’ll pick min = 0, and max = 6. Thus, max - min + 1 is 7.

Now let’s calculate all possible outcomes:

0 + (0 % 7) = 0
0 + (1 % 7) = 1
0 + (2 % 7) = 2
0 + (3 % 7) = 3
0 + (4 % 7) = 4
0 + (5 % 7) = 5
0 + (6 % 7) = 6

0 + (7 % 7) = 0
0 + (8 % 7) = 1
0 + (9 % 7) = 2

Look at the distribution of results. The results 0 through 2 come up twice, whereas 3 through 6 come up only once. This method has a clear bias towards low results. By extension, most cases involving this algorithm will behave similarly.

Now lets take a look at the result of the getRandomNumber() function above, using the same parameters as above (rand() returns a number between 0 and 9 (inclusive), min = 0 and max = 6). In this case, fraction = 1 / (9 + 1) = 0.1. max - min + 1 is still 7.

Calculating all possible outcomes:

0 + static_cast(7 * (0 * 0.1))) = 0 + static_cast(0) = 0
0 + static_cast(7 * (1 * 0.1))) = 0 + static_cast(0.7) = 0
0 + static_cast(7 * (2 * 0.1))) = 0 + static_cast(1.4) = 1
0 + static_cast(7 * (3 * 0.1))) = 0 + static_cast(2.1) = 2
0 + static_cast(7 * (4 * 0.1))) = 0 + static_cast(2.8) = 2
0 + static_cast(7 * (5 * 0.1))) = 0 + static_cast(3.5) = 3
0 + static_cast(7 * (6 * 0.1))) = 0 + static_cast(4.2) = 4
0 + static_cast(7 * (7 * 0.1))) = 0 + static_cast(4.9) = 4
0 + static_cast(7 * (8 * 0.1))) = 0 + static_cast(5.6) = 5
0 + static_cast(7 * (9 * 0.1))) = 0 + static_cast(6.3) = 6

The bias here is still slightly towards lower numbers (0, 2, and 4 appear twice, whereas 1, 3, 5, and 6 appear once), but it’s much more uniformly distributed.

Even though getRandomNumber() is a little more complicated to understand than the modulus alternative, we advocate for the division method because it produces a less biased result.

What is a good PRNG?

As I mentioned above, the PRNG we wrote isn’t a very good one. This section will discuss the reasons why. It is optional reading because it’s not strictly related to C or C++, but if you like programming you will probably find it interesting anyway.

In order to be a good PRNG, the PRNG needs to exhibit a number of properties:

First, the PRNG should generate each number with approximately the same probability. This is called distribution uniformity. If some numbers are generated more often than others, the result of the program that uses the PRNG will be biased!

For example, let’s say you’re trying to write a random item generator for a game. You’ll pick a random number between 1 and 10, and if the result is a 10, the monster will drop a powerful item instead of a common one. You would expect a 1 in 10 chance of this happening. But if the underlying PRNG is not uniform, and generates a lot more 10s than it should, your players will end up getting more rare items than you’d intended, possibly trivializing the difficulty of your game.

Generating PRNGs that produce uniform results is difficult, and it’s one of the main reasons the PRNG we wrote at the top of this lesson isn’t a very good PRNG.

Second, the method by which the next number in the sequence is generated shouldn’t be obvious or predictable. For example, consider the following PRNG algorithm: num = num + 1. This PRNG is perfectly uniform, but it’s not very useful as a sequence of random numbers!

Third, the PRNG should have a good dimensional distribution of numbers. This means it should return low numbers, middle numbers, and high numbers seemingly at random. A PRNG that returned all low numbers, then all high numbers may be uniform and non-predictable, but it’s still going to lead to biased results, particularly if the number of random numbers you actually use is small.

Fourth, all PRNGs are periodic, which means that at some point the sequence of numbers generated will begin to repeat itself. The length of the sequence before a PRNG begins to repeat itself is known as the period.

For example, here are the first 100 numbers generated from a PRNG with poor periodicity:

112	9	130	97	64	
31	152	119	86	53	
20	141	108	75	42	
9	130	97	64	31	
152	119	86	53	20	
141	108	75	42	9	
130	97	64	31	152	
119	86	53	20	141	
108	75	42	9	130	
97	64	31	152	119	
86	53	20	141	108	
75	42	9	130	97	
64	31	152	119	86	
53	20	141	108	75	
42	9	130	97	64	
31	152	119	86	53	
20	141	108	75	42	
9	130	97	64	31	
152	119	86	53	20	
141	108	75	42	9

You will note that it generated 9 as the second number, and 9 again as the 16th number. The PRNG gets stuck generating the sequence in-between these two 9’s repeatedly: 9-130-97-64-31-152-119-86-53-20-141-108-75-42-(repeat).

This happens because PRNGs are deterministic -- given some set of input values, they will produce the same output value every time. This means that once the PRNG encounters a set of inputs it has used before, it will start producing the same sequence of outputs it has produced before -- resulting in a loop.

A good PRNG should have a long period for all seed numbers. Designing an algorithm that meets this property can be extremely difficult -- most PRNGs will have long periods for some seeds and short periods for others. If the user happens to pick a seed that has a short period, then the PRNG won’t be doing a good job.

Despite the difficulty in designing algorithms that meet all of these criteria, a lot of research has been done in this area because of its importance to scientific computing.

std::rand() is a mediocre PRNG

The algorithm used to implement std::rand() can vary from compiler to compiler, leading to results that may not be consistent across compilers. Most implementations of rand() use a method called a Linear Congruential Generator (LCG). If you have a look at the first example in this lesson, you’ll note that it’s actually a LCG, though one with intentionally picked poor constants. LCGs tend to have shortcomings that make them not good choices for most kinds of problems.

One of the main shortcomings of rand() is that RAND_MAX is usually set to 32767 (essentially 15-bits). This means if you want to generate numbers over a larger range (e.g. 32-bit integers), rand() is not suitable. Also, rand() isn’t good if you want to generate random floating point numbers (e.g. between 0.0 and 1.0), which is often useful when doing statistical modelling. Finally, rand() tends to have a relatively short period compared to other algorithms.

That said, rand() is perfectly suitable for learning how to program, and for programs in which a high-quality PRNG is not a necessity.

For applications where a high-quality PRNG is useful, I would recommend Mersenne Twister (or one of its variants), which produces great results and is relatively easy to use. Mersenne Twister was adopted into C++11, and we’ll show how to use it later in this lesson.

Debugging programs that use random numbers

Programs that use random numbers can be difficult to debug because the program may exhibit different behaviors each time it is run. Sometimes it may work, and sometimes it may not. When debugging, it’s helpful to ensure your program executes the same (incorrect) way each time. That way, you can run the program as many times as needed to isolate where the error is.

For this reason, when debugging, it’s a useful technique to set the random seed (via std::srand) to a specific value (e.g. 0) that causes the erroneous behavior to occur. This will ensure your program generates the same results each time, making debugging easier. Once you’ve found the error, you can seed using the system clock again to start generating randomized results again.

Better random numbers using Mersenne Twister

C++11 added a ton of random number generation functionality to the C++ standard library, including the Mersenne Twister algorithm, as well as generators for different kinds of random distributions (uniform, normal, Poisson, etc…). This is accessed via the <random> header.

Here’s a short example showing how to generate random numbers in C++11 using Mersenne Twister (h/t to user Fernando):

Author's note

Before C++17, you need to add empty brackets to create die after the type
std::uniform_int_distribution<> die{ 1, 6 }

You’ll note that Mersenne Twister generates random 32-bit unsigned integers (not 15-bit integers like std::rand()), giving a lot more range. There’s also a version (std::mt19937_64) for generating 64-bit unsigned integers.

Random numbers across multiple functions

The above example create a random generator for use within a single function. What happens if we want to use a random number generator in multiple functions?

Although you can create a static local std::mt19937 variable in each function that needs it (static so that it only gets seeded once), it’s a little overkill to have every function that needs a random number generator seed and maintain its own local generator. A better option in most cases is to create a global random number generator (inside a namespace!). Remember how we told you to avoid non-const global variables? This is an exception (also note: std::rand() and std::srand() access a global object, so there’s precedent for this).

Using a random library

A perhaps better solution is to use a 3rd party library that handles all of this stuff for you, such as the header-only Effolkronium’s random library. You simply add the header to your project, #include it, and then you can start generating random numbers via Random::get(min, max).

Here’s the above program using Effolkronium’s library:

Help! My random number generator is generating the same sequence of random numbers!

If your random number generator is generating the same sequence of random numbers every time your program is run, you probably didn’t seed it properly. Make sure you’re seeding it with a value that changes each time the program is run (like std::time(nullptr)).

Help! My random number generator always generates the same first number!

The implementation of rand() in Visual Studio and a few other compilers has a flaw -- the first random number generated doesn’t change much for similar seed values. This means that when using std::time(nullptr) to seed your random number generator, the first result from rand() won’t change much in successive runs. However, the results of successive calls to rand() aren’t impacted, and will be sufficiently randomized.

The solution here, and a good rule of thumb in general, is to discard the first random number generated from the random number generator.

Help! My random number generator isn’t generating random numbers at all!

If your random number generator is generating the same number every time you ask it for a random number, then you are probably either reseeding the random number generator before generating a random number, or you’re creating a new random generator for each random number.

Here are two functions that exhibit the issue:

In both cases, the random number generator is being seeded each time before a random number is generated. This will cause a similar number to be generated each time.

In the top case, std::srand() is reseeding the built-in random number generator before rand() is called (by getRandomNumber()).

In the bottom case, we’re creating a new Mersenne Twister, seeding it, generating a single random number, and then destroying it.

For random results, you should only seed a random number generator once (generally at program initialization for std::srand(), or the point of creation for other random number generators), and then use that same random number generator for each successive random number generated.


The getOtherRandomNumber() example is one of the most common mistakes made later in quizzes. You won’t notice that getOtherRandomNumber() is broken until you start calling it more than once per second (Because the seed only changes once per second). Remember to make random number generators static or declare them outside of the function.

9.x -- Chapter 9 summary and quiz
9.4 -- Structs

519 comments to 9.5 — Random number generation

  • LorenDB

    First off, disclaimer: I finished this course several years ago (and loved it, thanks Alex/nascardriver!).

    Something interesting that I noticed on my Linux system when using std::rand that adds to its undesirability: when rand has been seeded with the time, if you run a small program to generate a random number several times in the same second, std::rand will generate the same number/number sequence each time. Possibly this could be worked around by using a time function that returned time in milli/micro/nano-seconds, but the obvious solution is to just use the STL's random stuff or another random library (in my case, probably Qt's).

    • nascardriver


      The issue you're observing is unrelated to `std::rand()` and linux, it's caused by re-seeding the random number generator. A random number generator should only be seeded once unless you have a reason to re-seed it (such as generating the same sequence as in another place, eg. "random" effects in video games should be the same for all clients).
      If the program runs quickly (<1s), or you launch multiple instances at the same time, the current time is a poor seed, as you have noticed. A better seed than the time is `std::random_device`. `std::random_device` can not always generate random seeds, call `std::random_device::entropy()` first to make sure it's available. If `std::random_device` cannot generate random numbers, you can fall back to other sources, eg. a high resolution clock.

  • Jake

    if we use a fixed number as a seed it seems random but not
    that's why we need to use a system clock to provide different number every time the program runs but
    if I loop and print unsigned ctime itself it doesn't provide a different number, so come ctime produce different random number and sequences while fixed number don't?

    #include <iostream>
    #include <cstdlib>
    #include <ctime>

    int main()
        // std::srand(static_cast<unsigned int>(std::time(nullptr)));

        for (int count{ 1 }; count <= 100; ++count)
            //std::cout << std::rand() << '\t';

            std::cout << static_cast<unsigned int>(std::time(nullptr)) << '\t';
            // it prints 1626499481 100 times which is a fixed number
            if (count % 5 == 0)
                std::cout << '\n';

        return 0;

  • James C

    Best practice/advice described as rule near top.

  • Ladyoftheroundtable

    So I've seen the the anti % speech before, but this time I decided to run a program that would run it for every number between 0 and 65535 exclusive, using %9. It did favor the lower numbers, but only by 1. and given that each number has over 7k occurrences this seems negligible at best. Perhaps if I was generating numbers with a max over 10k it might make a difference, but this seems a bit excessive for anything less than 100. (100 chosen due to it being significant if you're making random percentages.)

  • yeokaiwei

    Hi Alex,
    Could you teach us how to make a cryptographically secure pseudo-random number generator?

    "Do not write your own code to create a random number or use a “simple” random number generator offered by your programming language. It is vital that you use a cryptographically secure pseudo-random number generator (such as CSPRNG) with a seed from a source of sufficient entropy. Study the documentation of the random number generator library you choose to make sure it is cryptographically secure. Correct implementation of the CSPRNG library is critical to the security of the keys."

  • Rt

    Hi! I saw the code that Tobito posted below and changed it a little to test "how random" the random function is with different amount of iterations (from 10 to 1 billion), like this:

    And this is one of the outputs that I got:

    Maximum deviation for 10 iterations - 100.000000%       // this actually went up to 300% a few times

    Maximum deviation for 100 iterations - 60.000000%

    Maximum deviation for 1000 iterations - 29.000000%

    Maximum deviation for 10000 iterations - 3.200000%

    Maximum deviation for 100000 iterations - 1.860000%

    Maximum deviation for 1000000 iterations - 0.665000%

    Maximum deviation for 10000000 iterations - 0.151800%

    Maximum deviation for 100000000 iterations - 0.070430%

    Maximum deviation for 1000000000 iterations - 0.014121%  // this was maximum at 0.02%

    Time elapsed: 290.519000 seconds

    So as you can see, the deviation significantly drops when we loop it a lot more times. However, when the number of iterations are less than 1000 times bigger than the range of numbers you're getting from random() function, the numbers are distributed very unevenly.
    Also, you can run this code on your machine and see the results by yourself (but beware that it can take up to 5 minutes to run)

    P.S. I don't get it why isn't the code in a beautiful frame even with tags

  • Ramon

    Why not define

    As a constant? Why is it a non-const?

  • Waldo Lemmer

    Amazing lesson! Very thorough and well explained :)

    #A few suggestions:

    1. Section "What is a good PRNG?":
    It isn't clear that the table flows horizontally and not vertically. It was pretty confusing before I realized it flows horizontally. Maybe add a note?

    2. I think you should also explain `std::random_device`, and explain the difference between that and `std::mt19937`. I learned about it from [this video](

    3. When `std::time(nullptr)` is used as a seed and the program is run on different machines at the same time, they will all use the same values (if you use `std::srand()` or `std::mt19937`. This can be worked around by using something else for the seed, or by using a non-reproducible PRNG algorithm (like `std::random_device`). You might want to mention this.


    4. Section "std::rand() is a mediocre PRNG":
    > you’ll note that it’s actually a LCG
    "a" should be "an", because "LCG" is pronounced "El Cee Gee", which starts with a vowel.

    5. Section "Random numbers across multiple functions":
    > The above example create a random generator for use within a single function.
    "create" should be "creates"


    You're really great at writing tutorials and explaining things. I wish there were more of you, so you could write tutorials on other things as well :)

  • J34NP3T3R

    How come in the first example we had to use rand() 1x // Due to a flaw in some compilers, we need to call std::rand() once
    but in the std::time() example we no longer used rand() one time.

  • sk

    Hi! This my attempt at the Hi-lo game. Please suggest any improvements and optimizations.

  • sk

    Hi! Here is my Hi-Lo code. Can you suggest any optimizations and improvements?

    • nascardriver


      - Use an auto-formatter
      - Don't re-seed random number generators. `getRandom` isn't random
      - Don't use `goto`, use loops
      - Don't use integers for `bool`
      - The end of `playAgain` is identical to `return (play == 'y');`
      - Magic values: 8, 0, 100. Use constants.
      - Line 38 is always true because of the previous comparisons.
      - `--lives` can be made unconditional by placing it at the end of the loop (Or using a `for` loop)
      - "num" doesn't say anything about the variable. Every integer is a number. "target", "goal", "random" are more descriptive.

      • sk

        Hi! Thank you for replying.
        I didn't understand the 2nd,4th and 5th point.
        Also what alternative would you suggest for the 6th one.
        Thank you so much for this tutorial, its very helpful!

        • nascardriver

          2> Don't re-seed random number generators. `getRandom` isn't random
          See section "Help! My random number generator isn’t generating random numbers at all!".
          You're creating `mersenne` every time `getRandom()` is called, ie. you're re-seeding the generator and thus resetting the sequence. If you call `getRandom()` multiple times in 1 second, you'll get the same number every time. Create `mersenne` only once.

          4> Don't use integers for `bool`
          Line 23. `playAgain()` returns a `bool`, 0 is an integer. `return false;`

          5> The end of `playAgain` is identical to `return (play == 'y');`

          The body of the last condition and the code after the if-statement are identical, therefore you don't need the last condition. The code is identical to

          The function returns true if `play` is 'y', and `false` otherwise. You don't need an if-statement for that

          6> Magic values: 8, 0, 100. Use constants.
          The easiest solution is to add global constants

          Then use these constants everywhere you used a 0, 8, or 100 at.

          Though, global variables make code easier to break and less reusable. A better solution is to add `min` and `max` parameters to `getRandom()` and `gameMain()`. `gameMain()` also gets a `chances` parameter. You can then define the above constants in `main()` and `main()` can pass them to `getRandom()` and `gameMain()`.
          Doing it this way allows you to dynamically adjust the game's settings, eg. by first asking the user in which number range they want to play and starting the game with those values.

  • Luke

    I think we should include a call to "std::rand()" before the loop in the "PRNG sequences and seeding" example, just as we did in the previous example.
    Both for the sake of consistency, and because it makes the first PRNG result seem more random.

  • yeokaiwei

    Who is Effolkronium?

  • Tobito

    My compiler result show this
    10 6 8 2 6 5 10 3 1 4
    7 8 2 10 3 2 5 4 3 7
    1 9 6 7 8 8 3 6 2 10
    4 6 9 6 5 8 4 6 1 6
    2 8 8 5 5 1 4 5 4 7
    10 7 2 7 3 1 6 6 4 8
    9 7 6 7 2 2 1 6 4 7
    2 10 8 1 8 3 8 8 1 10
    5 10 1 2 10 3 10 5 9 10
    8 6 2 9 8 8 6 3 7 5
    1 = 9 counts
    2 = 11 counts
    3 = 8 counts
    4 = 8 counts
    5 = 9 counts
    6 = 14 counts
    7 = 10 counts
    8 = 15 counts
    9 = 5 counts /*this one*/
    10 = 11 counts

    when i was trying compiling afew time, sometimes it show me some parts of counts which is very below than the others. Is it a good distribution normal? especially i had been already using MT and uniform distribution

    • nascardriver

      That can happen. If you loop more often, the counts should deviate less from each other.

      The compiler is the program that converts your code into a binary (an executable). The compiler doesn't run your code. You compile code once and run your program as often as you like.

  • Tobito

    std::srand(static_cast<unsigned int> (std::chrono::high_resolution_clock::now));

    what is wrong with this code? i am trying using high_resolutioin_clock, but it show me error because can not convert from std::chrono

    • nascardriver

      `now` is a function, you have to call it with parentheses()
      It returns a `time_point`, which you can turn into a number using the `count()` member function.

  • Newprogramer

    anyone see that in Optional reading: How does the previous function work? 3. have (min - max +1)?

  • Suyash Mallik

    Hi.. I tried making a pseudo random number generator of my own using a static integer and my mind has been blown.
    [code]unsigned int PRNG() {
        static unsigned int seed{ 1235 };
        seed = seed * 812182 + 74163;
        return seed % 96144;
    } [\code]
    Now, irrespective of what seed I put in, after about 20-30 iterations, the value 47177 starts repeating. but curiously, when I put in 47177 as a seed value, the first generated number is not 47177! Please help, as this has me quite confounded for a while now!

    • Suyash Mallik

      I found that using putting the remainder operator in the assignment statement, along with the other arithmetic operators, solved the problem.

  • an old man and c++

    I could not distinguish die{1,6} from die(mersenne) at first as Jimmy.
    But, when I referred 'constructor' in this tutorial, I understand it.
    die{1,6} is a constructor call, and  die(mersenne) is a member function(operator()) call.

    die{1,6} is brace initialization which call the constructor std::uniform_int_distribution(1,6). Of course, direct initialization die(1,6) is allowed.
    die(mersenne) is a member function call by using operator().

  • sam p

    Excellent tutorial.
    Clear AND comprehensive.
    Many Thanks.

  • Simon+Gable+Lundmark

    Hi! First of all thanks for this entire website. It is absolutely excellent.

    I just wanted to suggest moving the note about rand() behaviour in Visual Studio further up and highlighting it a bit, because I was wracking my brain for upwards of an hour before I gave up getting it to work properly while trying to deconstruct what I was doing at "Generating random numbers between two arbitrary values" and "Optional reading: How does the previous function work?" .

    I saw one of the other comments struggling with the same, likely at an earlier point of this page than the clarification appears.

    Just a suggestion! Again, a million thanks! :)

  • Here is my attempt at a hi-lo game, and every time, the "random" number is actually three. Can you find anything wrong with my implementation?

    Also, I tried the Mersenne Twister, and std::uniform_int_distribution spit out errors C2955: 'std::uniform_int_distribution' use of class template requires template argument list, and C2514: 'std::uniform_int_distribution' class template cannot be constructed.

    • nascardriver

      Discard the first result of `std::rand()` by calling it in `main`. The first result is non-random in VS.
      You need C++17 or higher to use `std::uniform_int_distribution` without brackets. Update your compiler. If you can't (Update your compiler), use

  • Uyph

    Hi, i dont know if you'd answer this but... you haven't specified how to add the Random header to the project in the 'using a Random library' section. Is it built in or do we have to manually write it up?

  • It is me

    This part i just like

  • litaci

    the following code is just returning the minimum value again and again.
    during debugging, i saw the identifier fraction is just ignored by the compiler.

  • Jimmy

    It's hard to pinpoint my question, but i guess it has to to with the syntax of the mersenne twister.

    'std::uniform_int_distribution die {1,6}' has the same syntax as that of a variable declaration but when you call upon it you used 'die(mersenne)' which syntax wise looks more like a function than variable.

    so what is std::uniform_int_distribution? a type def/alias variable? a function or something entirely different ? I'm getting these mixed up.

    • nascardriver

      `std::uniform_int_distribution` is a type with a function call operator, which allows using `die` (`die` is a variable) like a function.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]