6

For example, the following expression:

r = (rand() % 10)+1;

Generates a random number from 1-10.

How can we make it generate random numbers from 0-10?

Thanks.

1
  • 1
    Understanding the answers on your previous question will answer this question. Commented Feb 7, 2011 at 9:37

5 Answers 5

16

You're almost there! The rand() function returns a random value in a pretty large range (0 to RAND_MAX). The use of the modulus operator wraps this down into a smaller range (from 0 to 9, since you're modding by 10) and then the +1 moves this to be from 1 to 10.

To get values between 0 and 10, you can take rand and mod its value by 11:

r = rand() % 11;

More generally, to get random values in the range [0, n], you can write

r = rand() % (n + 1);

And finally, to get values in the range [k, n + k], you can write

r = rand() % (n + 1) + k;

Of course, as purists will point out, this isn't necessarily going to give you truly uniform values because modding rand() by some value will not distribute all the integers evenly. This usually isn't a problem (you'll be off by a very, very small amount), but if it is you may want to consider looking into a more robust random number generator than rand().

Sign up to request clarification or add additional context in comments.

3 Comments

You have a off by one mistake since you talk about a half-open interval in the text, but generate a closed interval in the code.
@CodeInChaos- Whoops! My bad. :-) I'll fix that right away.
And typically the severest problem with rand() the non uniform distribution of a single random variable, but the correlation between random variables.
11

You leave out the +1 to start with 0. And since there are 11 different values you want, you need to calculate the remainder modulo 11 instead of 10.

r = rand() % 11;

Note that you need to seed a PRNG so it doesn't always produce the same sequence.

And the standard rand() function sucks. The quality of random numbers is very low, and not fit for many purposes. I strongly recommend using a better generator.

A Mersenne twister is a popular choice, and in one my projects I used Well512 since it's fast, good and easy to implement.

If the user must not predict the random numbers even those good PRNGs are not enough and you have to choose a cryptographic PRNG. They can neither be predicted (with realistic computational power) nor be distinguished from real random numbers unless you know the seed. They are a bit slower though.

4 Comments

Actually, it's fit for the vast majority of cases. The number of people playing computer games far outweighs the number of statisticians on the planet :-) But +1 for the right answer anyhow.
I've seen it break down for even simple simulations like a random walk.
@paxdiablo Computer games sometimes even need a cryptographically strong PRNG. You wouldn't want the PRNG for item drops in an online RPG be predictable.
actually it wouldn't matter. There's sufficient variation from the clients for which it would drop. In more formal terms: if you take a true random sample of the output of a proper pseudo-random number generator, the results will be random. (proper PRNG to disqualify the likes of xkcd.com/221 )
5

Generating a uniform distribution is much simpler and less error prone in C++11 using std::uniform_real_distribution or for the integer case std::uniform_int_distribution. Here is a sample using std::uniform_real_distribution which displays a simple graphic to give a rough demonstration that it is uniform:

#include <iostream>
#include <iomanip>
#include <string>
#include <random>

int main()
{
    std::random_device rd;

    //
    // Engines 
    //
    std::mt19937 e2(rd());
    //std::knuth_b e2(rd());
    //std::default_random_engine e2(rd()) ;

    std::uniform_real_distribution<> dist(0, 10);

    const int nstars=95;     // maximum number of stars to distribute
    const int nintervals=10; // number of intervals

    int p[nintervals]={};

    for (int i=0; i<100000; ++i)
    {
      double number = dist(e2);
      ++p[int(number)];
    }

    std::cout << std::fixed; std::cout.precision(1);

    for (int i=0; i<nintervals; ++i)
    {
      std::cout << float(i) << "-" << std::setw(4) << float(i+1) << ": ";
      std::cout << std::string(p[i]*nstars/100000,'*') << std::endl;
    }

    return 0 ;
}

Sample result:

0.0- 1.0: *********
1.0- 2.0: *********
2.0- 3.0: *********
3.0- 4.0: *********
4.0- 5.0: *********
5.0- 6.0: *********
6.0- 7.0: *********
7.0- 8.0: *********
8.0- 9.0: *********
9.0-10.0: *********

Some of the sample code was taken from this reference.

Comments

1

Here is simpler way of generating random numbers with modern C++.

#include <iostream>
#include <random>

int main()
{
    std::random_device device;
    std::default_random_engine engine(device());
    std::uniform_int_distribution<int> r(0, 10);
    std::cout << r(engine) << std::endl;
}

2 Comments

Why would this be a better solution then (rand() % 11)? Besides the fact that you can select different engines and sources. You should add more context to your answer.
Is it safe to declare a new std::uniform_distribution each time a random number is needed? I'd like to boil this down to a simple random(min, max) function instead of having to copy-paste all this code everywhere I need a random number. I wouldn't want to keep uniform_int_distribution objects around for every possible combination of min and max.
0

This is a basic way to generate random numbers. The line of code that uses static_cast seeds the random number generator based on the current time, which means you get more numbers besides between 0 and 10 instead of just one.

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

using namespace std;

int main()
{
    srand(static_cast<unsigned int>(time(0))); // Seed random number generator
    unsigned int r = rand() % 10; // Generate random number
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.