How does modulus and rand() work?
So, I've been nuts on this.
rand() % 6 will always produce a result between 0-5.
However when I need between, let's say 6-12.
Should I have rand() % 6 + 6
0+6 = 6.
1+6 = 7.
...
5+6 = 11. ???
So do I need to + 7 If I want the interval 6-12? But then, 0+7 =7. When will it randomize 6?
What am I missing here? Which one is the correct way to have a randomized number between 6 and 12? And why? It seems like I am missing something here.
If C++11 is an option then you should use the random header and uniform_int_distrubution. As James pointed out in the comments using rand and %
has a lot of issues including a biased distribution:
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 e2(rd());
std::uniform_int_distribution<int> dist(6, 12);
for (int n = 0; n < 10; ++n) {
std::cout << dist(e2) << ", " ;
}
std::cout << std::endl ;
}
if you have to use rand then this should do:
rand() % 7 + 6
Update
A better method using rand
would be as follows:
6 + rand() / (RAND_MAX / (12 - 6 + 1) + 1)
I obtained this from the C FAQ and it is explained How can I get random integers in a certain range? question.
Update 2
Boost is also an option:
#include <iostream>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
int main()
{
boost::random::mt19937 gen;
boost::random::uniform_int_distribution<> dist(6, 12);
for (int n = 0; n < 10; ++n) {
std::cout << dist(gen) << ", ";
}
std::cout << std::endl ;
}
You need rand() % 7 + 6.
Lowest number from rand() %7: 0. Highest number from rand() %7: 6.
0 + 6 = 6. 6 + 6 = 12.
The modulus operation a % b
computes the remainder of the division a / b
. Obviously the remainder of a division must be less than b
and if a
is a random positive integer then a%b
is a random integer in the range 0 .. (b-1)
In the comments you mention:
rand()%(max-min)+min
This algorithm produces values in the half-open range [min, max). (That is, max is outside the range, and simply denotes the boundary. Since we're talking about ranges of integers this range is equivalent to the closed range [min, max-1].)
When you write '0 - 5' or '6 - 12' those are closed ranges. To use the above equation you have to use the values that denote the equivalent half open range: [0, 6) or [6, 13).
rand() % (6-0) + 0
rand() % (13-6) + 6
Note that rand() % (max-min) + min
is just a generalization of the rule you've apparently already learned: that rand() % n
produces values in the range 0 - (n-1). The equivalent half-open range is [0, n), and rand() % n
== rand() % (n-0) + 0
.
So the lesson is: don't confuse half-open ranges for closed ranges.
A second lesson is that this shows another way in which <random>
is easier to use than rand()
and manually computing your own distributions. The built-in uniform_int_distribution
allows you to directly state the desired, inclusive range. If you want the range 0 - 5 you say uniform_int_distibution<>(0, 5)
, and if you want the range 6 - 12 then you say uniform_int_distribution<>(6, 12)
.
#include <random>
#include <iostream>
int main() {
std::default_random_engine eng;
std::uniform_int_distribution<> dist(6, 12);
for (int i=0; i<10; ++i)
std::cout << dist(eng) << " ";
}
rand()%7+6
is more terse, but that doesn't mean it is easier to use.