Related
I need a function which would generate a random integer in a given range (including boundary values). I don't have unreasonable quality/randomness requirements; I have four requirements:
I need it to be fast. My project needs to generate millions (or sometimes even tens of millions) of random numbers and my current generator function has proven to be a bottleneck.
I need it to be reasonably uniform (use of rand() is perfectly fine).
the minimum-maximum ranges can be anything from <0, 1> to <-32727, 32727>.
it has to be seedable.
I currently have the following C++ code:
output = min + (rand() * (int)(max - min) / RAND_MAX)
The problem is that it is not really uniform - max is returned only when rand() = RAND_MAX (for Visual C++ it is 1/32727). This is a major issue for small ranges like <-1, 1>, where the last value is almost never returned.
So I grabbed pen and paper and came up with following formula (which builds on the (int)(n + 0.5) integer rounding trick):
But it still doesn't give me a uniform distribution. Repeated runs with 10000 samples give me ratio of 37:50:13 for values values -1, 0. 1.
Is there a better formula? (Or even whole pseudo-random number generator function?)
The simplest (and hence best) C++ (using the 2011 standard) answer is:
#include <random>
std::random_device rd; // Only used once to initialise (seed) engine
std::mt19937 rng(rd()); // Random-number engine used (Mersenne-Twister in this case)
std::uniform_int_distribution<int> uni(min,max); // Guaranteed unbiased
auto random_integer = uni(rng);
There isn't any need to reinvent the wheel, worry about bias, or worry about using time as the random seed.
A fast, somewhat better than yours, but still not properly uniform distributed solution is
output = min + (rand() % static_cast<int>(max - min + 1))
Except when the size of the range is a power of 2, this method produces biased non-uniform distributed numbers regardless the quality of rand(). For a comprehensive test of the quality of this method, please read this.
If your compiler supports C++0x and using it is an option for you, then the new standard <random> header is likely to meet your needs. It has a high quality uniform_int_distribution which will accept minimum and maximum bounds (inclusive as you need), and you can choose among various random number generators to plug into that distribution.
Here is code that generates a million random ints uniformly distributed in [-57, 365]. I've used the new std <chrono> facilities to time it as you mentioned performance is a major concern for you.
#include <iostream>
#include <random>
#include <chrono>
int main()
{
typedef std::chrono::high_resolution_clock Clock;
typedef std::chrono::duration<double> sec;
Clock::time_point t0 = Clock::now();
const int N = 10000000;
typedef std::minstd_rand G; // Select the engine
G g; // Construct the engine
typedef std::uniform_int_distribution<> D; // Select the distribution
D d(-57, 365); // Construct the distribution
int c = 0;
for (int i = 0; i < N; ++i)
c += d(g); // Generate a random number
Clock::time_point t1 = Clock::now();
std::cout << N/sec(t1-t0).count() << " random numbers per second.\n";
return c;
}
For me (2.8 GHz Intel Core i5) this prints out:
2.10268e+07 random numbers per second.
You can seed the generator by passing in an int to its constructor:
G g(seed);
If you later find that int doesn't cover the range you need for your distribution, this can be remedied by changing the uniform_int_distribution like so (e.g., to long long):
typedef std::uniform_int_distribution<long long> D;
If you later find that the minstd_rand isn't a high enough quality generator, that can also easily be swapped out. E.g.:
typedef std::mt19937 G; // Now using mersenne_twister_engine
Having separate control over the random number generator, and the random distribution can be quite liberating.
I've also computed (not shown) the first four "moments" of this distribution (using minstd_rand) and compared them to the theoretical values in an attempt to quantify the quality of the distribution:
min = -57
max = 365
mean = 154.131
x_mean = 154
var = 14931.9
x_var = 14910.7
skew = -0.00197375
x_skew = 0
kurtosis = -1.20129
x_kurtosis = -1.20001
(The x_ prefix refers to "expected".)
Let's split the problem into two parts:
Generate a random number n in the range 0 through (max-min).
Add min to that number
The first part is obviously the hardest. Let's assume that the return value of rand() is perfectly uniform. Using modulo will add bias
to the first (RAND_MAX + 1) % (max-min+1) numbers. So if we could magically change RAND_MAX to RAND_MAX - (RAND_MAX + 1) % (max-min+1), there would no longer be any bias.
It turns out that we can use this intuition if we are willing to allow pseudo-nondeterminism into the running time of our algorithm. Whenever rand() returns a number which is too large, we simply ask for another random number until we get one which is small enough.
The running time is now geometrically distributed, with expected value 1/p where p is the probability of getting a small enough number on the first try. Since RAND_MAX - (RAND_MAX + 1) % (max-min+1) is always less than (RAND_MAX + 1) / 2,
we know that p > 1/2, so the expected number of iterations will always be less than two
for any range. It should be possible to generate tens of millions of random numbers in less than a second on a standard CPU with this technique.
Although the above is technically correct, DSimon's answer is probably more useful in practice. You shouldn't implement this stuff yourself. I have seen a lot of implementations of rejection sampling and it is often very difficult to see if it's correct or not.
Use the Mersenne Twister. The Boost implementation is rather easy to use and is well tested in many real-world applications. I've used it myself in several academic projects, such as artificial intelligence and evolutionary algorithms.
Here's their example where they make a simple function to roll a six-sided die:
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>
boost::mt19937 gen;
int roll_die() {
boost::uniform_int<> dist(1, 6);
boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
return die();
}
Oh, and here's some more pimping of this generator just in case you aren't convinced you should use it over the vastly inferior rand():
The Mersenne Twister is a "random
number" generator invented by Makoto
Matsumoto and Takuji Nishimura; their
website includes numerous
implementations of the algorithm.
Essentially, the Mersenne Twister is a
very large linear-feedback shift
register. The algorithm operates on a
19,937 bit seed, stored in an
624-element array of 32-bit unsigned
integers. The value 2^19937-1 is a
Mersenne prime; the technique for
manipulating the seed is based on an
older "twisting" algorithm -- hence
the name "Mersenne Twister".
An appealing aspect of the Mersenne
Twister is its use of binary
operations -- as opposed to
time-consuming multiplication -- for
generating numbers. The algorithm also
has a very long period, and good
granularity. It is both fast and
effective for non-cryptographic applications.
int RandU(int nMin, int nMax)
{
return nMin + (int)((double)rand() / (RAND_MAX+1) * (nMax-nMin+1));
}
This is a mapping of 32768 integers to (nMax-nMin+1) integers. The mapping will be quite good if (nMax-nMin+1) is small (as in your requirement). Note however that if (nMax-nMin+1) is large, the mapping won't work (For example - you can't map 32768 values to 30000 values with equal probability). If such ranges are needed - you should use a 32-bit or 64-bit random source, instead of the 15-bit rand(), or ignore rand() results which are out-of-range.
Assume min and max are integer values,
[ and ] means include this value,
( and ) means do not include this value,
using the above to get the right value using C++'s rand().
Reference:
For ()[] define, visit Interval (mathematics).
For the rand and srand function or RAND_MAX define,
visit std::rand.
[min, max]
int randNum = rand() % (max - min + 1) + min
(min, max]
int randNum = rand() % (max - min) + min + 1
[min, max)
int randNum = rand() % (max - min) + min
(min, max)
int randNum = rand() % (max - min - 1) + min + 1
Here is an unbiased version that generates numbers in [low, high]:
int r;
do {
r = rand();
} while (r < ((unsigned int)(RAND_MAX) + 1) % (high + 1 - low));
return r % (high + 1 - low) + low;
If your range is reasonably small, there is no reason to cache the right-hand side of the comparison in the do loop.
I recommend the Boost.Random library. It's super detailed and well-documented, lets you explicitly specify what distribution you want, and in non-cryptographic scenarios can actually outperform a typical C library rand implementation.
Notice that in most suggestions the initial random value that you have got from rand() function, which is typically from 0 to RAND_MAX, is simply wasted. You are creating only one random number out of it, while there is a sound procedure that can give you more.
Assume that you want [min,max] region of integer random numbers. We start from [0, max-min]
Take base b=max-min+1
Start from representing a number you got from rand() in base b.
That way you have got floor(log(b,RAND_MAX)) because each digit in base b, except possibly the last one, represents a random number in the range [0, max-min].
Of course the final shift to [min,max] is simple for each random number r+min.
int n = NUM_DIGIT-1;
while(n >= 0)
{
r[n] = res % b;
res -= r[n];
res /= b;
n--;
}
If NUM_DIGIT is the number of digit in base b that you can extract and that is
NUM_DIGIT = floor(log(b,RAND_MAX))
then the above is as a simple implementation of extracting NUM_DIGIT random numbers from 0 to b-1 out of one RAND_MAX random number providing b < RAND_MAX.
In answers to this question, rejection sampling was already addressed, but I wanted to suggest one optimization based on the fact that rand() % 2^something does not introduce any bias as already mentioned above.
The algorithm is really simple:
calculate the smallest power of 2 greater than the interval length
randomize one number in that "new" interval
return that number if it is less than the length of the original interval
reject otherwise
Here's my sample code:
int randInInterval(int min, int max) {
int intervalLen = max - min + 1;
//now calculate the smallest power of 2 that is >= than `intervalLen`
int ceilingPowerOf2 = pow(2, ceil(log2(intervalLen)));
int randomNumber = rand() % ceilingPowerOf2; //this is "as uniform as rand()"
if (randomNumber < intervalLen)
return min + randomNumber; //ok!
return randInInterval(min, max); //reject sample and try again
}
This works well especially for small intervals, because the power of 2 will be "nearer" to the real interval length, and so the number of misses will be smaller.
PS: Obviously avoiding the recursion would be more efficient (there isn't any need to calculate over and over the log ceiling...), but I thought it was more readable for this example.
The following is the idea presented by Walter. I wrote a self-contained C++ class that will generate a random integer in the closed interval [low, high]. It requires C++11.
#include <random>
// Returns random integer in closed range [low, high].
class UniformRandomInt {
std::random_device _rd{};
std::mt19937 _gen{_rd()};
std::uniform_int_distribution<int> _dist;
public:
UniformRandomInt() {
set(1, 10);
}
UniformRandomInt(int low, int high) {
set(low, high);
}
// Set the distribution parameters low and high.
void set(int low, int high) {
std::uniform_int_distribution<int>::param_type param(low, high);
_dist.param(param);
}
// Get random integer.
int get() {
return _dist(_gen);
}
};
Example usage:
UniformRandomInt ur;
ur.set(0, 9); // Get random int in closed range [0, 9].
int value = ur.get()
The formula for this is very simple, so try this expression,
int num = (int) rand() % (max - min) + min;
//Where rand() returns a random number between 0.0 and 1.0
The following expression should be unbiased if I am not mistaken:
std::floor( ( max - min + 1.0 ) * rand() ) + min;
I am assuming here that rand() gives you a random value in the range between 0.0 and 1.0 not including 1.0 and that max and min are integers with the condition that min < max.
what is the best way to do this? my compiler shows RAND_MAX = 32,767. so I'm curious how I can get a uniform random generation of values between 0 and 100,000?
I'll just put juanchopanza's comment into answer.
Use the <random> header if your compiler provides it (C++11).
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 10000);
std::cout << dis(gen) << std::endl;
You should probably download and use a serious PRNG then, such as the ones available in the Gnu Scientific Library.
I found the following function on some website a long time ago. The author claimed that function gives a good uniformity.
#define RS_SCALE (1.0 / (1.0 + RAND_MAX))
double drand(void)
{
double d;
do {
d = (((rand () * RS_SCALE) + rand ()) * RS_SCALE + rand ()) * RS_SCALE;
} while (d >= 1); /* Round off */
return(d);
}
As noted in a comment below this gives answer in range 0..1, so you have to multiply by 100000, i.e. drand()*100000.
How I've found was to first, #include <time.h>, then you can writesrand(time(NULL)); to seed a value into the random function. Then all you've got to do is use this line: (rand() % 99999 + 1);. That should give you a random value in between 0 and 100,000. You can also assign that to a variable if you need to: int myVar = (rand() % 99999 + 1);. Hope that helps! (And I hope that I'm totally correct. I'm still getting my CS degree and still learning C++, but I've done this before and it's worked.)
Here is your code:
100000.0f * ((float)rand() / 32767.0f)
This will produce random float from 0 to 100000 but you can use any positive number other than 100000 here.
Update:
Indeed (thanks to psj's comment below) I've realized above covers ~1/3 of 0..100000 range.
I cannot find a way to generate random number from uniform distribution in an open interval like (0,1).
(double)rand()/RAND_MAX;
will this include 0 and 1? If yes, what is the correct way to generate random number in an open interval?
Take a look at std::uniform_real_distribution! You can use a more professional pseudo random number generator than the bulit-in of <cstdlib> called std::rand(). Here's a code example that print outs 10 random numbers in range [0,1):
#include <iostream>
#include <random>
int main()
{
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(0.0,1.0);
for (int i=0; i<10; ++i)
std::cout << distribution(generator) << endl;
return 0;
}
It is very unlikely to get exactly zero. If it is very important for you to not to get 0, you can check for it and generate another number.
And of course you can use random number engine specified, as std::mt19937(that is "very" random) or one of the fastest, the std::knuth_b.
I haven't written C++ in ages but try the following code:
double M = 0.00001, N = 0.99999;
double rNumber = M + rand() / (RAND_MAX / (N - M + 1) + 1);
I haven't programmed in C++ for a number of years now, but when I did the implementation of rand was compiler specific. Implementations varied as to whether they covered [0,RAND_MAX], [0,RAND_MAX), (0,RAND_MAX], or (0,RAND_MAX). That may have changed, and I'm sure somebody will chime in if it has.
Assume that the implementation is over the closed interval [0,RAND_MAX], then (double)(rand()+1)/(RAND_MAX+2); should yield an open interval U(0,1) unless RAND_MAX is pushing up against the word size, in which case cast to long. Adjust the additive constants if your generator covers the range differently.
An even better solution would be to ditch rand and use something like the Mersenne Twister from the Boost libraries. MT has different calls which explicitly give you control over the open/closed range of the results.
Given uniform distribution of a RNG with closed interval [a, b], the easiest method is to simply discard unwanted values an throw the dice again. This is both numerically stable and practically the fastest method to maintain uniformity.
double myRnD()
{
double a = 0.0;
while (a == 0.0 || a == 1.0) a = (double)rand() * (1.0 / (double)RAND_MAX);
return a;
}
(Disclaimer: RAND_MAX would have to be a power of two and < 2^52)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Generating random integer from a range
I just started learning C++ and I'm trying to generate a random integer thats either 1, 2, or 3. I searched around and all the examples I see of generating random numbers are confusing and always different from the last example I looked at. Is there a simple way to do this?
The modulo solution is the most straightforward but it usually loses randomness as modulo as the tendency to "eat up" the lowest bits of the result.
A more random way is to map [0,1[ over [a,b[ in a linear way:
int roll(int min, int max)
{
// x is in [0,1[
double x = rand()/static_cast<double>(RAND_MAX+1);
// [0,1[ * (max - min) + min is in [min,max[
int that = min + static_cast<int>( x * (max - min) );
return that;
}
A generic version is trivially derived from these to get a roll( T min, T max) version.
Try this:
srand(time(NULL));
int randNum = (rand() % 3) + 1; // you don't need the (...) surrounding rand() % 3 but it helps for clarity
This works by taking the remainder of the return value of the rand function divided by three (which can be 0, 1, or 2) and adding one (to come up with either 1, 2, or 3).
Make sure you include the cstdlib and ctime headers.
Also, call srand only one time, not each time you generate a random number.
I need a function which would generate a random integer in a given range (including boundary values). I don't have unreasonable quality/randomness requirements; I have four requirements:
I need it to be fast. My project needs to generate millions (or sometimes even tens of millions) of random numbers and my current generator function has proven to be a bottleneck.
I need it to be reasonably uniform (use of rand() is perfectly fine).
the minimum-maximum ranges can be anything from <0, 1> to <-32727, 32727>.
it has to be seedable.
I currently have the following C++ code:
output = min + (rand() * (int)(max - min) / RAND_MAX)
The problem is that it is not really uniform - max is returned only when rand() = RAND_MAX (for Visual C++ it is 1/32727). This is a major issue for small ranges like <-1, 1>, where the last value is almost never returned.
So I grabbed pen and paper and came up with following formula (which builds on the (int)(n + 0.5) integer rounding trick):
But it still doesn't give me a uniform distribution. Repeated runs with 10000 samples give me ratio of 37:50:13 for values values -1, 0. 1.
Is there a better formula? (Or even whole pseudo-random number generator function?)
The simplest (and hence best) C++ (using the 2011 standard) answer is:
#include <random>
std::random_device rd; // Only used once to initialise (seed) engine
std::mt19937 rng(rd()); // Random-number engine used (Mersenne-Twister in this case)
std::uniform_int_distribution<int> uni(min,max); // Guaranteed unbiased
auto random_integer = uni(rng);
There isn't any need to reinvent the wheel, worry about bias, or worry about using time as the random seed.
A fast, somewhat better than yours, but still not properly uniform distributed solution is
output = min + (rand() % static_cast<int>(max - min + 1))
Except when the size of the range is a power of 2, this method produces biased non-uniform distributed numbers regardless the quality of rand(). For a comprehensive test of the quality of this method, please read this.
If your compiler supports C++0x and using it is an option for you, then the new standard <random> header is likely to meet your needs. It has a high quality uniform_int_distribution which will accept minimum and maximum bounds (inclusive as you need), and you can choose among various random number generators to plug into that distribution.
Here is code that generates a million random ints uniformly distributed in [-57, 365]. I've used the new std <chrono> facilities to time it as you mentioned performance is a major concern for you.
#include <iostream>
#include <random>
#include <chrono>
int main()
{
typedef std::chrono::high_resolution_clock Clock;
typedef std::chrono::duration<double> sec;
Clock::time_point t0 = Clock::now();
const int N = 10000000;
typedef std::minstd_rand G; // Select the engine
G g; // Construct the engine
typedef std::uniform_int_distribution<> D; // Select the distribution
D d(-57, 365); // Construct the distribution
int c = 0;
for (int i = 0; i < N; ++i)
c += d(g); // Generate a random number
Clock::time_point t1 = Clock::now();
std::cout << N/sec(t1-t0).count() << " random numbers per second.\n";
return c;
}
For me (2.8 GHz Intel Core i5) this prints out:
2.10268e+07 random numbers per second.
You can seed the generator by passing in an int to its constructor:
G g(seed);
If you later find that int doesn't cover the range you need for your distribution, this can be remedied by changing the uniform_int_distribution like so (e.g., to long long):
typedef std::uniform_int_distribution<long long> D;
If you later find that the minstd_rand isn't a high enough quality generator, that can also easily be swapped out. E.g.:
typedef std::mt19937 G; // Now using mersenne_twister_engine
Having separate control over the random number generator, and the random distribution can be quite liberating.
I've also computed (not shown) the first four "moments" of this distribution (using minstd_rand) and compared them to the theoretical values in an attempt to quantify the quality of the distribution:
min = -57
max = 365
mean = 154.131
x_mean = 154
var = 14931.9
x_var = 14910.7
skew = -0.00197375
x_skew = 0
kurtosis = -1.20129
x_kurtosis = -1.20001
(The x_ prefix refers to "expected".)
Let's split the problem into two parts:
Generate a random number n in the range 0 through (max-min).
Add min to that number
The first part is obviously the hardest. Let's assume that the return value of rand() is perfectly uniform. Using modulo will add bias
to the first (RAND_MAX + 1) % (max-min+1) numbers. So if we could magically change RAND_MAX to RAND_MAX - (RAND_MAX + 1) % (max-min+1), there would no longer be any bias.
It turns out that we can use this intuition if we are willing to allow pseudo-nondeterminism into the running time of our algorithm. Whenever rand() returns a number which is too large, we simply ask for another random number until we get one which is small enough.
The running time is now geometrically distributed, with expected value 1/p where p is the probability of getting a small enough number on the first try. Since RAND_MAX - (RAND_MAX + 1) % (max-min+1) is always less than (RAND_MAX + 1) / 2,
we know that p > 1/2, so the expected number of iterations will always be less than two
for any range. It should be possible to generate tens of millions of random numbers in less than a second on a standard CPU with this technique.
Although the above is technically correct, DSimon's answer is probably more useful in practice. You shouldn't implement this stuff yourself. I have seen a lot of implementations of rejection sampling and it is often very difficult to see if it's correct or not.
Use the Mersenne Twister. The Boost implementation is rather easy to use and is well tested in many real-world applications. I've used it myself in several academic projects, such as artificial intelligence and evolutionary algorithms.
Here's their example where they make a simple function to roll a six-sided die:
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>
boost::mt19937 gen;
int roll_die() {
boost::uniform_int<> dist(1, 6);
boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
return die();
}
Oh, and here's some more pimping of this generator just in case you aren't convinced you should use it over the vastly inferior rand():
The Mersenne Twister is a "random
number" generator invented by Makoto
Matsumoto and Takuji Nishimura; their
website includes numerous
implementations of the algorithm.
Essentially, the Mersenne Twister is a
very large linear-feedback shift
register. The algorithm operates on a
19,937 bit seed, stored in an
624-element array of 32-bit unsigned
integers. The value 2^19937-1 is a
Mersenne prime; the technique for
manipulating the seed is based on an
older "twisting" algorithm -- hence
the name "Mersenne Twister".
An appealing aspect of the Mersenne
Twister is its use of binary
operations -- as opposed to
time-consuming multiplication -- for
generating numbers. The algorithm also
has a very long period, and good
granularity. It is both fast and
effective for non-cryptographic applications.
int RandU(int nMin, int nMax)
{
return nMin + (int)((double)rand() / (RAND_MAX+1) * (nMax-nMin+1));
}
This is a mapping of 32768 integers to (nMax-nMin+1) integers. The mapping will be quite good if (nMax-nMin+1) is small (as in your requirement). Note however that if (nMax-nMin+1) is large, the mapping won't work (For example - you can't map 32768 values to 30000 values with equal probability). If such ranges are needed - you should use a 32-bit or 64-bit random source, instead of the 15-bit rand(), or ignore rand() results which are out-of-range.
Assume min and max are integer values,
[ and ] means include this value,
( and ) means do not include this value,
using the above to get the right value using C++'s rand().
Reference:
For ()[] define, visit Interval (mathematics).
For the rand and srand function or RAND_MAX define,
visit std::rand.
[min, max]
int randNum = rand() % (max - min + 1) + min
(min, max]
int randNum = rand() % (max - min) + min + 1
[min, max)
int randNum = rand() % (max - min) + min
(min, max)
int randNum = rand() % (max - min - 1) + min + 1
Here is an unbiased version that generates numbers in [low, high]:
int r;
do {
r = rand();
} while (r < ((unsigned int)(RAND_MAX) + 1) % (high + 1 - low));
return r % (high + 1 - low) + low;
If your range is reasonably small, there is no reason to cache the right-hand side of the comparison in the do loop.
I recommend the Boost.Random library. It's super detailed and well-documented, lets you explicitly specify what distribution you want, and in non-cryptographic scenarios can actually outperform a typical C library rand implementation.
Notice that in most suggestions the initial random value that you have got from rand() function, which is typically from 0 to RAND_MAX, is simply wasted. You are creating only one random number out of it, while there is a sound procedure that can give you more.
Assume that you want [min,max] region of integer random numbers. We start from [0, max-min]
Take base b=max-min+1
Start from representing a number you got from rand() in base b.
That way you have got floor(log(b,RAND_MAX)) because each digit in base b, except possibly the last one, represents a random number in the range [0, max-min].
Of course the final shift to [min,max] is simple for each random number r+min.
int n = NUM_DIGIT-1;
while(n >= 0)
{
r[n] = res % b;
res -= r[n];
res /= b;
n--;
}
If NUM_DIGIT is the number of digit in base b that you can extract and that is
NUM_DIGIT = floor(log(b,RAND_MAX))
then the above is as a simple implementation of extracting NUM_DIGIT random numbers from 0 to b-1 out of one RAND_MAX random number providing b < RAND_MAX.
In answers to this question, rejection sampling was already addressed, but I wanted to suggest one optimization based on the fact that rand() % 2^something does not introduce any bias as already mentioned above.
The algorithm is really simple:
calculate the smallest power of 2 greater than the interval length
randomize one number in that "new" interval
return that number if it is less than the length of the original interval
reject otherwise
Here's my sample code:
int randInInterval(int min, int max) {
int intervalLen = max - min + 1;
//now calculate the smallest power of 2 that is >= than `intervalLen`
int ceilingPowerOf2 = pow(2, ceil(log2(intervalLen)));
int randomNumber = rand() % ceilingPowerOf2; //this is "as uniform as rand()"
if (randomNumber < intervalLen)
return min + randomNumber; //ok!
return randInInterval(min, max); //reject sample and try again
}
This works well especially for small intervals, because the power of 2 will be "nearer" to the real interval length, and so the number of misses will be smaller.
PS: Obviously avoiding the recursion would be more efficient (there isn't any need to calculate over and over the log ceiling...), but I thought it was more readable for this example.
The following is the idea presented by Walter. I wrote a self-contained C++ class that will generate a random integer in the closed interval [low, high]. It requires C++11.
#include <random>
// Returns random integer in closed range [low, high].
class UniformRandomInt {
std::random_device _rd{};
std::mt19937 _gen{_rd()};
std::uniform_int_distribution<int> _dist;
public:
UniformRandomInt() {
set(1, 10);
}
UniformRandomInt(int low, int high) {
set(low, high);
}
// Set the distribution parameters low and high.
void set(int low, int high) {
std::uniform_int_distribution<int>::param_type param(low, high);
_dist.param(param);
}
// Get random integer.
int get() {
return _dist(_gen);
}
};
Example usage:
UniformRandomInt ur;
ur.set(0, 9); // Get random int in closed range [0, 9].
int value = ur.get()
The formula for this is very simple, so try this expression,
int num = (int) rand() % (max - min) + min;
//Where rand() returns a random number between 0.0 and 1.0
The following expression should be unbiased if I am not mistaken:
std::floor( ( max - min + 1.0 ) * rand() ) + min;
I am assuming here that rand() gives you a random value in the range between 0.0 and 1.0 not including 1.0 and that max and min are integers with the condition that min < max.