5.9 — 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.

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. 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 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 srand() with a call to std::time(nullptr) (or std::time(0) if your compiler is pre-C++11).

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() return 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 (min - max + 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 modulus 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 eventually begin to repeat itself. As mentioned before, PRNGs are deterministic, and given an input number, a PRNG will produce the same output number every time. Consider what happens when a PRNG generates a number it has previously generated. From that point forward, it will begin to duplicate the sequence between the first occurrence of that number and the next occurrence of that number over and over. The length of this sequence 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).

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.

rand() may return the same first value on successive calls on some compilers

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 time() to seed your random number generator, the first result from rand() won’t change much in successive runs. This problem is compounded by calling getRandomNumber(), which compresses similar inputs into the same output number. The results of successive calls to rand() aren’t impacted.

However, there’s an easy fix: call rand() once and discard the result. Then you can use rand() as normal in your program.

Recommendation: After calling srand(), call rand() once and discard the first result to avoid this issue.

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 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.

Random numbers in C++11

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):

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!

There’s so much functionality in <random> that it really warrants its own section. We’ll look to cover that in a future lesson in more detail.

5.10 -- std::cin, extraction, and dealing with invalid text input
5.8 -- Break and continue

307 comments to 5.9 — Random number generation

  • Edward

    Does anyone know how to solve the error below when running the Mersenne Twister example in Code::Blocks? I'm using version 13.12.

    terminate called after throwing an instance of 'std::runtime_error'
      what():  random_device::random_device(const std::string&)

    This application has requested the Runtime to terminate it in an unusual way.
    Please contact the application's support team for more information.

    • Alex

      Apparently MinGW doesn't have an implementation of random_device on Windows. That's annoying.

      Fortunately seeding with the system clock still works.

      On Code::Blocks, replace:


  • SuperSiggson

    Isn't something as simple as

    perfectly enough when generating random numbers of fairly trivial importance? I think its a lot easier to learn (and understand).

    • SuperSiggson


      To clarify, if

      it would produce random numbers between (including) 250 and 284.

    • Alex

      Yes, and in fact, the previous version of the lesson used that algorithm.

      However, as some readers correctly noted, that algorithms really only works well when range is small. For larger ranges, you run into problems where lower numbers can occur more often than higher numbers. Consider a range of 10000 and min value of 0. If the random number picked is between 0 and 29999, the returned result is evenly distributed between 0 to 9999. However, if the random number picked is between 30000 and 32767, the returned result is only between 0 and 2767. That means the numbers between 0 and 2767 have a 33% greater chance of occurring than numbers between 2768 and 9999. That's a pretty bad skew.

      The current algorithm is a little more complicated, but it also works for any range, small or large. For that reason, it's a better solution, despite the small amount of additional complexity.

      • erad

        I'm afraid I do not follow the explanation you made in this comment, Alex. I thought the motivation for your comment was to highlight why the trivial approach suggested in the OP seemed to be more suited to smaller ranges than larger ones. Instead of showing how differently-sized ranges/spans impact the distributions of the random numbers generated, you seemed to have just fiddled with the numbers returned by rand(). I thought we had no control over what the rand() function returns!

        In my view, since we have no control over the returns from the rand() function (it is a constant in our analysis), our task should have been to show the uniformity(or the lack thereof) of our distribution against differently-sized ranges/spans.

        I hope I made my confusion clear.

        • Alex

          We don't have control over what rand() returns, but we can assume it returns a relatively uniform distribution.

          Given that it's hard to talk about distributions in abstract, I chose a specific example to help illustrate one case where using modulus with a large range can lead to uneven distributions, where low numbers may occur significantly more often than high numbers (leading to poor uniformity). By understanding one specific case, it's easier to understand why this is true in general.

  • cpplx

    yay! the infamous RNG.
    id say the optional tag shall be removed from the last part of the lesson for it is the most important part of it

  • Methos

    Is there any way to characterize how 'good' a PRNG has to be to not be observable in for example, a game?

    The only example I can think of was from one of the online guides for Final Fantasy 12 where you could (simplifying greatly) force a rare chest drop by loading the game, performing a fixed number of actions, and then using a particular spell that didn't make random calls (it always teleported enemies 'away').

    If I had to guess, someone cracked the code of the game to find that, as I can't imagine stumbling on that behavior as a player.

    If we're writing a RNG from scratch, for whatever reason, I wonder if we might be better off making multiple time calls-once to get a seed, then say time()%X where we pick X to set a maximum number of times the scratch RNG function runs before a value is called to be used. I would think that would play havok with the period of the thing, so long as you had picked values (which if I understand the wikipedia link, it's possible) that cover the range.

    • Alex

      > Is there any way to characterize how ‘good’ a PRNG has to be to not be observable in for example, a game?

      I think it really depends on how often you're calling the PRNG, and whether the results are visible to the user. The more you call it and the more visible the results are, the more likely a bad PRNG will produce noticeably bad results.

      A good PRNG shouldn't benefit from throwing a certain number of results away before using a result. Every result should be sufficiently randomized. However, a bad PRNG could (in theory) actually become less random by doing such a thing.

      • Methos

        Yeah, I guess it's easier to understand the bad cases than the good.

        If I have a PRNG with period 30000, and my 'solution' is to skip 9 results (which seems at first to be the most obvious thing to do if you've ever shuffled cards until everyone at the table is happy), all I've done is give myself a PRNG with period 3000.

        I suspect, thinking a little further it wouldn't have to be that good at all for entertainment purposes. I can see how for academic purposes, you're going to want a very large period if your model requires a billion PRNG calls as fast as your hardware will allow, but not so much in a dungeon crawler, where all the user sees are:
        -Is there a monster in this area (yes/no)?
        -What kind is it (maybe three or four options in a given area)?
        -Does one attacker hit the other (yes/no) and for how much damage (could be d6+2 for something like a tabletop game)?
        -Loot (could be a check of a table like in Skyrim or fixed with one item possible like Dragon Warrior)?

        So, in 30 seconds of gameplay, that's around 10-20 calls, or about 13 hours before you'd expect the sequence to repeat. Which is probably adequate for a single player game (where on will surely have moved on in that timeframe) but not for say, an MMO (where people grind endgame content for the better part of a year).

        • Alex

          Well, if the dungeons themselves are randomly generated, that's a lot of randomization calls at the time the dungeon is generated.

          The period is also relevant only if you're calculating the same results in the same order. For example, random value 55 (on a scale of 0 to 99) might map to "Orc" when generating a monster, but "dagger" when generating an item. If it's used once in each context, even though the PRNG is repeating values, the results will be different because the context is different. So practically speaking, as long as you're not using the randomized results in a homogenous manner, you could probably get away with a smaller period.

          • Methos

            I wrote the following mainly out of curiosity about the 'bad' numbers mentioned for LCGs. I just thought I'd post it in the event anyone might want to experiment a bit like I did. What I'm doing is simulating a four sided die roll and visually checking that the guys at wikipedia were right about full periods (they unsurprisingly appear to be, but it helps to actually see it) and checking via the tally array how often the same face is rolled consecutively (should be .25). Small or very large numbers were probably going to be bad (and were) but I was surprised how bad numbers for a around half of m turned out (a=65, c=1, m=128 gave a tally total of .5).

            A warning is probably warranted that if you don't follow the rules for picking a, c, and m, there's a chance your iterated value winds up in an endless loop that never hits 1 again.

  • Todd


    "Take games for example -- Without (without) random events,"

    "take the result of rand() can (and) convert it"

    "The length of this sequence is known as the period" (you need to add a period (ironically) to the end of this sentence)

    "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 is a different sequence than the one in the table to which you're referring)

    "because of it’s (its) importance to scientific computing."

  • C++ newbie

    Who the heck came up with "midnight on Jan 1, 1970"????  It's so arbitrary...

    Why not 1971, or February 3?  Why Jan 1, 1970, 12:00 AM!?!?!?!?!?!??!?!?

    • Alex

      It seems arbitrary because... it was arbitrary. 🙂

      Unix engineers needed to pick a date and time to start counting from, so they picked the earliest time in the decade they were in. You can read more about it on the Wikipedia article on Unix time.

  • Jatn

    I wanted to find out a correlation between the seed you provide and number rand () generates , so i made a program that forms a table of seed you give and the random number it forms with that seed and here it is .

    It worked well and i noticed that consecutive random numbers differ by either 3 or 4 . So i modified my program so that it clearly shows the difference between
    consecutive random numbers .Here is the code

    It also ran fine but unfortunately i couldn't see any pattern of 3's and 4's in difference column .Sadly i can't copy things from the ".exe" file. Try it guys and please let me know if u see a pattern.

  • Jay

    Gives a complier warning in Xcode for Mac, says precision may be lost. I'm guessing its because of the different data types between what the srand() function expects and the time(0); function provides.

    To get round this issue I did this:

    Is there a better way?

    • Alex

      time() returns a value of type time_t, whereas srand() expects a value of type unsigned int.

      time_t is a typedef that doesn't specify what the underlying data type is. Often it's an unsigned int, but it could be something else. Many unix systems use a signed integer (either 32 or 64 bits).

      Using a static_cast as you have is a good way to tell the compiler "I meant to do this, so stop warning me about it".

      Although you could lose precision by converting a 64-bit signed integer to a 32-bit unsigned integer, it's unlikely to matter too much because it's the low bits that change every second, and those are the ones that get preserved in the conversion.

  • Philorbust

    How to have the random generator only generate even numbers? Great site!

  • dice3000

    srand(time(0)) - this kind of inital seed values is absolutely bad, because it is a timestamp (amount of seconds since 1970.01.01). So if you are calling your main function multiple times in a row, your random numbers will follow the same pattern, since the seed values only changes by a couple of seconds, and that is very small change to a number 1375984340 (2013.03.08 20:52). What wee need for a seed value is computer microtime (microseconds) of current time, because its changes rapidly

    • Alex

      You should only seed your random generator once per program. How close two seeds are together shouldn't matter unless your PRNG is very poor. Even using rand(), which isn't great, using two consecutive seed numbers (e.g. 5 vs 6) will generate vastly different sequences of numbers.

      The main problem with using a time-based seed is that a clever adversary could change the system clock to make your program run the same way every time. This could allow the adversary to game the system, or allow them to compromise some bit of crypto or security.

      But hopefully if that matters, you're reading more advanced articles before attempting to write such a program. This is an introductory article.

  • mori

    If you are on a unix/linux system you should use /dev/random or /dev/urandom, those do have more "physical" randomness, mouse movements, etc.

  • So I tried to make a random number generator between 1 and 13. And at the end when you guess correctly it shows how many times you guessed. It is funny though because it seems whenever I enter 3 into the program it comes out blank and ends the program.

    Here is the code:

    using namespace std;

    int counter=0;

    unsigned int getRandom(int nHigh, int nLow){
    return (rand() % (nHigh - nLow + 1)) + nLow;
    int main(){
    int x, y;
    int nGuess;

    cout << "Enter a gues between 1 and 6: " <> nGuess;
    if (nGuess < getRandom(y,x)){
    cout << "too low try again" < getRandom(y,x)){
    cout << "Too high try again" << endl;
    else if (nGuess == getRandom(y,x)){
    cout << "Congradulations!" << endl;
    cout << "Number of Guesses: " << counter << endl;

    system ("PAUSE");
    return 0;

  • coyote

    Just as a heads up, I noticed that when I ran the last program for random numbers I did get output that was as high as: 2033645517. This is on a linux box so it might be that different systems/compilers have different defaults for the RAND_MAX constant.

  • Dragon

    Where do you put the code that keeps the application up for more than a millisecond?

  • cubbi

    While commonly used in bad textbooks, the % operator should NOT be used to limit the range of values produced by std::rand(): it results in a non-uniform distribution. If you must use std::rand(), divide by RAND_MAX (cast to double).

  • Just a quick question, what will happen with the function time() in 69 years from 1970 (year 2039). Will every program in the world that uses time() crash? I imagine no one tought this would be an issue in 1970 xD.

    • Alex

      time() will experience overflow, and programs will think it's 1970 again.

      I think this will be a much bigger deal than Y2K turned out to be.

  • Jack Sparrow II

    My question is how do I generate random numbers without generating the same ones multiple times?

    • Wolf

      I'm wondering the same thing.

      I need to write a program that randomizes a deck of cards, but I can't be assigning the same random value to multiple cards in the deck.

      • Alex

        Great questions. In this case, you don't want random numbers, you want a random ordering of a fixed set of objects.

        I'd tackle the card shuffling exercise like this:
        * Give each card a unique identifier (an integer or an enumerator).
        * Create an array of length 52.
        * Add the cards to the array (in order is fine).
        * Use a for loop to step through each card in the array. For each card, pick a random number between 0 and 51, and swap that card with the card at the randomly picked location.

        That should give you a decent shuffle.

  • Jjtricky

    I really don't get this line:

    Surely, this would break the line after the fourth number, as:

    Therefore, the line is ended

  • Alex, you have a v good understanding of the field which you deal with. Thanks for all these detailed tutorials. Keep up the good work.
    Thankyou Alex.

  • .......

    Any way to create a random char?

    • You can use ASCII numbers and use static_cast to make them into characters

    • You can use ASCII numbers like Mike said.

      //Setting the range between 97 and 122 (97 = a and 122 = z)
      int RandomNumber = ((rand() % 26) + 97);

      // I assigned the random created ASCI number to a char variable
      // If you just want to print, use "cout << static_cast<char>(RandomNumber)"
      char RandomCharacter = static_cast<char>(RandomNumber);

  • I dont understand in your first example how

    is going to give us a number between 0 and 32767.Isnt % supposed to give the remainder of the division?And since nSeed is always the same number,since we do the same arithetic operations with it each time,wont the remainder be the same,resulting in the return value being the same?

    I hope you understand my question ;P

    • A1) Remainder can't be bigger than divider. That explains the range.

      A2) Since we used static keyword, compiler doesn't reset the variable after using it. Seed changes everytime.

      nSeed = (8253729 * nSeed + 2396403)

      First time, nSeed is 5323. Second time, it becomes the result of that operation. Third time, it changes again and this goes on.

  • Hank

    I have an issue with your mapping implementation (the GetRandomNumber function). It's fine for small ranges like the dice example, but for larger target ranges, you can get serious uniformity issues. For example, let's say you want a random number between 0 and 21,844 (about 2/3 of rand()'s RAND_MAX). With GetRandomNumber, for numbers that already fall in the target range, you get a 1-to-1 mapping (0 becomes 0, 1 becomes 1, etc.), then for the rest of the domain of rand(), the output essentially starts over at 0 and overlaps onto the first half of the target range. Therefore, you're twice as likely to get a number between 0 and 10,922 as you are to get one between 10,923 and 21,844, when the probabilities should be equal! Thus I'd recommend instead just using *, /, + and - to convert (probably need to cast to a float first, then truncate).

  • Why do you need to declare nSeed with the static key word with this? I don't see the point in needing its file scope.

    • baldo

      nSeed is a local variable for the PRNG function. The static keyword has another meaning when used for local variables. In this case, nSeed variable "retains it’s value even after the scope in which it has been created has been exited! Fixed duration variables are only created (and initialized) once, and then they are persisted throughout the life of the program." See more here: Lesson 4.3. the static keyword

      • sunoval

        baldo, Thanks for your useful comments. The use of "static" is definitely the core component of the whole algorithm here. I was trying to figure out the function of static here for a while although I have learned Lesson 4.3. before. Thanks

  • once we needed to use the actual eth packet numbers and some system data to generate a rand number in an embedded device...

    in some cases it's really difficult to generate (so-called)random numbers.

  • Markos

    Hi , thank you for this information , but i have a question. Is there a way that i can generate a random number between two ranges of numbers( like, i want to generate a random number that is in (0 to 200) or (400 to 1300) ).

    with best wishes

    • Josh Browning

      I'm not sure if there's a better way to do this, but you could generate a random boolean (i.e. rand()%2) and then use an if statement to determine which range to use. So, for example, if the random boolean is 0, then pick a random number between 0 to 200, else pick one between 400 to 1300. If you want one range to show up more often than the other, just pick a random integer first (maybe from 0 to 9) and have only 0 and 1 lead to the range 400 to 1300. Then, 80% of the time you will have a random number between 0 to 200, and 20% between 400 to 1300 (if your RNG is good).

  • Dan

    Hey Alex, thanks for making the great tutorials.

    I'm wondering if there's any way to generate 30 random numbers and store them in an array. I'm able to generate a random number and store it in an array, but whenever I try to access the array every single indexed number in it is the same random number. I'm thinking that this is perhaps because the random number is based on the system clock and all 30 numbers are created at the same time?

    • I don't see any reason why what you are doing wouldn't work. If you initialize the array using a loop like this:

      you should get a different number in each slot.

      If you're not, then I suspect you're either initializing your array incorrectly or your rand() really isn't returning random numbers for some reason.

  • Abby

    Is it possible to create a random statement for a group of words that I come up with, not just random numbers?

    • Not directly. However, there are a couple of options:

      1) Put your words in an array, and then use a random number to index that array. I cover arrays in the next chapter, I think.
      2) Write a function that uses a switch statement to return a given word for an input number.

  • diyon

    Hi, I'm new to C++. and would like to know how to write a programe to generate random numbers uniformly distributed between 0 and 1.
    Thank you,

    • rand() generates numbers between 0 and RAND_MAX. So to generate numbers between 0 and 1, simply divide the result of rand() by RAND_MAX (make sure to use a cast to cast the result to a double, otherwise you'll get integer division).


      Note that this will only generate numbers that are a multiple of 1/ RAND_MAX. If you need something with more granularity, you'll have to use a different algorithm, like Mersenne Twister.

  • Pathik

    This code in visual c++ 2005 express edition gives this error at compile time:

    'error C2661: 'time' : no overloaded function takes 0 arguments'

  • hi Alex, it's good to see you've put in something about random numbers,now I can make games with random numbers....
    thanks for the great tutorial alex

Leave a Comment

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