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.
This question already has answers here:
Random float number generation
(14 answers)
Closed 7 years ago.
The title pretty much says it all. I've looked online but I couldn't find anything for this language. I've seen the following:
((double) rand() / (RAND_MAX)) with no luck. I'd also like to avoid using external library's.
The value should be a float as I'm working out X,Y coordinates.
If you are using C++11, you can use the random header for this. You will need to create a generator, then define a distribution over this generator, and then you can use the generator and the distribution to get your results. You need to include random
#include <random>
Then define the generator and your distribution
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(-1,1); //doubles from -1 to 1
Then you can get random numbers like so
double random_number = distribution(generator);
If you need more information it is available here http://www.cplusplus.com/reference/random/
Maybe ((double) rand() / (RAND_MAX)) * 2 - 1.
Don't simply use rand() because it's not random, just pseudo random!
unsigned int rand_interval(unsigned int min, unsigned int max)
{
int r;
const unsigned int range = 1 + max - min;
const unsigned int buckets = RAND_MAX / range;
const unsigned int limit = buckets * range;
/* Create equal size buckets all in a row, then fire randomly towards
* the buckets until you land in one of them. All buckets are equally
* likely. If you land off the end of the line of buckets, try again. */
do
{
r = rand();
} while (r >= limit);
return min + (r / buckets);
}
This is a fully functioning code. (Don't forget to seed rand with srand() in main!
Note> I can't take credit for it as I have also seen it somewhere online and I'm using it myself for some time.
I need to generate random numbers within a specified interval, [max;min].
Also, the random numbers should be uniformly distributed over the interval, not located to a particular point.
Currenly I am generating as:
for(int i=0; i<6; i++)
{
DWORD random = rand()%(max-min+1) + min;
}
From my tests, random numbers are generated around one point only.
Example
min = 3604607;
max = 7654607;
Random numbers generated:
3631594
3609293
3630000
3628441
3636376
3621404
From answers below: OK, RAND_MAX is 32767. I am on C++ Windows platform. Is there any other method to generate random numbers with a uniform distribution?
Why rand is a bad idea
Most of the answers you got here make use of the rand function and the modulus operator. That method may not generate numbers uniformly (it depends on the range and the value of RAND_MAX), and is therefore discouraged.
C++11 and generation over a range
With C++11 multiple other options have risen. One of which fits your requirements, for generating a random number in a range, pretty nicely: std::uniform_int_distribution. Here's an example:
#include <iostream>
#include <random>
int main()
{
const int range_from = 0;
const int range_to = 1000;
std::random_device rand_dev;
std::mt19937 generator(rand_dev());
std::uniform_int_distribution<int> distr(range_from, range_to);
std::cout << distr(generator) << '\n';
}
Try it online on Godbolt
And here's the running example.
Template function may help some:
template<typename T>
T random(T range_from, T range_to) {
std::random_device rand_dev;
std::mt19937 generator(rand_dev());
std::uniform_int_distribution<T> distr(range_from, range_to);
return distr(generator);
}
Other random generators
The <random> header offers innumerable other random number generators with different kind of distributions including Bernoulli, Poisson and normal.
How can I shuffle a container?
The standard provides std::shuffle, which can be used as follows:
#include <iostream>
#include <random>
#include <vector>
int main()
{
std::vector<int> vec = {4, 8, 15, 16, 23, 42};
std::random_device random_dev;
std::mt19937 generator(random_dev());
std::shuffle(vec.begin(), vec.end(), generator);
std::for_each(vec.begin(), vec.end(), [](auto i){std::cout << i << '\n';});
}
Try it online on Godbolt
The algorithm will reorder the elements randomly, with a linear complexity.
Boost.Random
Another alternative, in case you don't have access to a C++11+ compiler, is to use Boost.Random. Its interface is very similar to the C++11 one.
Warning: Do not use rand() for statistics, simulation, cryptography or anything serious.
It's good enough to make numbers look random for a typical human in a hurry, no more.
See Jefffrey's reply for better options, or this answer for crypto-secure random numbers.
Generally, the high bits show a better distribution than the low bits, so the recommended way to generate random numbers of a range for simple purposes is:
((double) rand() / (RAND_MAX+1)) * (max-min+1) + min
Note: make sure RAND_MAX+1 does not overflow (thanks Demi)!
The division generates a random number in the interval [0, 1); "stretch" this to the required range. Only when max-min+1 gets close to RAND_MAX you need a "BigRand()" function like posted by Mark Ransom.
This also avoids some slicing problems due to the modulo, which can worsen your numbers even more.
The built-in random number generator isn't guaranteed to have a the quality required for statistical simulations. It is OK for numbers to "look random" to a human, but for a serious application, you should take something better - or at least check its properties (uniform distribution is usually good, but values tend to correlate, and the sequence is deterministic). Knuth has an excellent (if hard-to-read) treatise on random number generators, and I recently found LFSR to be excellent and darn simple to implement, given its properties are OK for you.
I'd like to complement Shoe's and peterchen's excellent answers with a short overview of the state of the art in 2015:
Some good choices
randutils
The randutils library (presentation) is an interesting novelty, offering a simple interface and (declared) robust random capabilities. It has the disadvantages that it adds a dependence on your project and, being new, it has not been extensively tested. Anyway, being free (MIT License) and header-only, I think it's worth a try.
Minimal sample: a die roll
#include <iostream>
#include "randutils.hpp"
int main() {
randutils::mt19937_rng rng;
std::cout << rng.uniform(1,6) << "\n";
}
Even if one is not interested in the library, the website provides many interesting articles about the theme of random number generation in general and the C++ library in particular.
Boost.Random
Boost.Random (documentation) is the library which inspired C++11's <random>, with whom it shares much of the interface. While theoretically also being an external dependency, Boost has by now a status of "quasi-standard" library, and its Random module could be regarded as the classical choice for good-quality random number generation. It features two advantages with respect to the C++11 solution:
it is more portable, just needing compiler support for C++03
its random_device uses system-specific methods to offer seeding of good quality
The only small flaw is that the module offering random_device is not header-only, one has to compile and link boost_random.
Minimal sample: a die roll
#include <iostream>
#include <boost/random.hpp>
#include <boost/nondet_random.hpp>
int main() {
boost::random::random_device rand_dev;
boost::random::mt19937 generator(rand_dev());
boost::random::uniform_int_distribution<> distr(1, 6);
std::cout << distr(generator) << '\n';
}
While the minimal sample does its work well, real programs should use a pair of improvements:
make mt19937 a thread_local: the generator is quite plump (more than 2 KB) and is better not allocated on the stack
seed mt19937 with more than one integer: the Mersenne Twister has a big state and can take benefit of more entropy during initialization
Some not-so-good choices
The C++11 library
While being the most idiomatic solution, the <random> library does not offer much in exchange for the complexity of its interface even for the basic needs. The flaw is in std::random_device: the Standard does not mandate any minimal quality for its output (as long as entropy() returns 0) and, as of 2015, MinGW (not the most used compiler, but hardly an esoteric choice) will always print 4 on the minimal sample.
Minimal sample: a die roll
#include <iostream>
#include <random>
int main() {
std::random_device rand_dev;
std::mt19937 generator(rand_dev());
std::uniform_int_distribution<int> distr(1, 6);
std::cout << distr(generator) << '\n';
}
If the implementation is not rotten, this solution should be equivalent to the Boost one, and the same suggestions apply.
Godot's solution
Minimal sample: a die roll
#include <iostream>
#include <random>
int main() {
std::cout << std::randint(1,6);
}
This is a simple, effective and neat solution. The only defect is it will take a while to compile – about two years, providing C++17 is released on time and the experimental randint function is approved into the new Standard. Maybe by that time also the guarantees on the seeding quality will improve.
The worse-is-better solution
Minimal sample: a die roll
#include <cstdlib>
#include <ctime>
#include <iostream>
int main() {
std::srand(std::time(nullptr));
std::cout << (std::rand() % 6 + 1);
}
The old C solution is considered harmful, and for good reasons (see the other answers here or this detailed analysis). Still, it has its advantages: is is simple, portable, fast and honest, in the sense it is known that the random numbers one gets are hardly decent, and therefore one is not tempted to use them for serious purposes.
The accounting troll solution
Minimal sample: a die roll
#include <iostream>
int main() {
std::cout << 9; // http://dilbert.com/strip/2001-10-25
}
While 9 is a somewhat unusual outcome for a regular die roll, one has to admire the excellent combination of good qualities in this solution, which manages to be the fastest, simplest, most cache-friendly and most portable one. By substituting 9 with 4, one gets a perfect generator for any kind of Dungeons & Dragons die, while still avoiding the symbol-laden values 1, 2 and 3. The only small flaw is that, because of the bad temper of Dilbert's accounting trolls, this program actually engenders undefined behavior.
If RAND_MAX is 32767, you can double the number of bits easily.
int BigRand()
{
assert(INT_MAX/(RAND_MAX+1) > RAND_MAX);
return rand() * (RAND_MAX+1) + rand();
}
If you are concerned about randomness and not about speed, you should use a secure random number generation method. There are several ways to do this... The easiest one being to use OpenSSL's Random Number Generator.
You can also write your own using an encryption algorithm (like AES). By picking a seed and an IV and then continuously re-encrypting the output of the encryption function. Using OpenSSL is easier, but less manly.
If you are able to, use Boost. I have had good luck with their random library.
uniform_int should do what you want.
You should look at RAND_MAX for your particular compiler/environment.
I think you would see these results if rand() is producing a random 16-bit number. (you seem to be assuming it will be a 32-bit number).
I can't promise this is the answer, but please post your value of RAND_MAX, and a little more detail on your environment.
This should provide a uniform distribution over the range [low, high) without using floats, as long as the overall range is less than RAND_MAX.
uint32_t rand_range_low(uint32_t low, uint32_t high)
{
uint32_t val;
// only for 0 < range <= RAND_MAX
assert(low < high);
assert(high - low <= RAND_MAX);
uint32_t range = high-low;
uint32_t scale = RAND_MAX/range;
do {
val = rand();
} while (val >= scale * range); // since scale is truncated, pick a new val until it's lower than scale*range
return val/scale + low;
}
and for values greater than RAND_MAX you want something like
uint32_t rand_range(uint32_t low, uint32_t high)
{
assert(high>low);
uint32_t val;
uint32_t range = high-low;
if (range < RAND_MAX)
return rand_range_low(low, high);
uint32_t scale = range/RAND_MAX;
do {
val = rand() + rand_range(0, scale) * RAND_MAX; // scale the initial range in RAND_MAX steps, then add an offset to get a uniform interval
} while (val >= range);
return val + low;
}
This is roughly how std::uniform_int_distribution does things.
Check what RAND_MAX is on your system -- I'm guessing it is only 16 bits, and your range is too big for it.
Beyond that see this discussion on: Generating Random Integers within a Desired Range and the notes on using (or not) the C rand() function.
Using a Mersenne Twister engine (C++11):
#include <random>
// Returns a random integer within the range [min, max]
int generateRandomInt(const int min, const int max) {
static bool is_seeded = false;
static std::mt19937 generator;
// Seed once
if (!is_seeded) {
std::random_device rd;
generator.seed(rd());
is_seeded = true;
}
// Use a Mersenne Twister engine to pick a random number
// within the given range
std::uniform_int_distribution<int> distribution(min, max);
return distribution(generator);
}
If you want numbers to be uniformly distributed over the range, you should break your range up into a number of equal sections that represent the number of points you need. Then get a random number with a min/max for each section.
As another note, you should probably not use rand() as it's not very good at actually generating random numbers. I don't know what platform you're running on, but there is probably a better function you can call like random().
This is not the code, but this logic may help you.
static double rnd(void)
{
return (1.0 / (RAND_MAX + 1.0) * ((double)(rand())));
}
static void InitBetterRnd(unsigned int seed)
{
register int i;
srand(seed);
for(i = 0; i < POOLSIZE; i++)
{
pool[i] = rnd();
}
}
// This function returns a number between 0 and 1
static double rnd0_1(void)
{
static int i = POOLSIZE - 1;
double r;
i = (int)(POOLSIZE*pool[i]);
r = pool[i];
pool[i] = rnd();
return (r);
}
The solution given by man 3 rand for a number between 1 and 10 inclusive is:
j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
In your case, it would be:
j = min + (int) ((max-min+1) * (rand() / (RAND_MAX + 1.0)));
Of course, this is not perfect randomness or uniformity as some other messages are pointing out, but this is enough for most cases.
This is the solution I came up with:
#include "<stdlib.h>"
int32_t RandomRange(int32_t min, int32_t max) {
return (rand() * (max - min + 1) / (RAND_MAX + 1)) + min;
}
This is a bucket solution, conceptually similar to the solutions that use rand() / RAND_MAX to get a floating point range between 0-1 and then round that into a bucket. However, it uses purely integer math, and takes advantage of integer division flooring to round down the value to the nearest bucket.
It makes a few assumptions. First, it assumes that RAND_MAX * (max - min + 1) will always fit within an int32_t. If RAND_MAX is 32767 and 32 bit int calculations are used, the the maximum range you can have is 32767. If your implementation has a much larger RAND_MAX, you can overcome this by using a larger integer (like int64_t) for the calculation. Secondly, if int64_t is used but RAND_MAX is still 32767, at ranges greater than RAND_MAX you will start to get "holes" in the possible output numbers. This is probably the biggest issue with any solution derived from scaling rand().
Testing over a huge number of iterations nevertheless shows this method to be very uniform for small ranges. However, it is possible (and likely) that mathematically this has some small bias and possibly develops issues when the range approaches RAND_MAX. Test it for yourself and decide if it meets your needs.
By their nature, a small sample of random numbers doesn't have to be uniformly distributed. They're random, after all. I agree that if a random number generator is generating numbers that consistently appear to be grouped, then there is probably something wrong with it.
But keep in mind that randomness isn't necessarily uniform.
A solution
((double) rand() / (RAND_MAX+1)) * (max-min+1) + min
Warning: Don't forget due to stretching and possible precision errors (even if RAND_MAX were large enough), you'll only be able to generate evenly distributed "bins" and not all numbers in [min,max].
A solution using Bigrand
Warning: Note that this doubles the bits, but still won't be able to generate all numbers in your range in general, i.e., it is not necessarily true that BigRand() will generate all numbers between in its range.
Information: Your approach (modulo) is "fine" as long as the range of rand() exceeds your interval range and rand() is "uniform". The error for at most the first max - min numbers is 1/(RAND_MAX +1).
Also, I suggest to switch to the new random package in C++11 too, which offers better and more varieties of implementations than rand().
Minimal implementation with C++11:
#include <random>
int randrange (int min, int max) {
static std::random_device rd; // Static in case init is costly
return std::uniform_int_distribution {min, max} (rd);
}
This is an old thread, but I just stumbled on it now. Here's my take:
As others rightly pointed out, MSBs tend to be more randomly distributed than LSBs in most RNGs. That implies that taking the modulo (%) of rand() is doomed: e.g. the extremely frequent random(2) would only return the single LSB... which is extremely badly distributed in most RNGs.
On the other hand, if you need your random(N) to be very fast (as I do: I'm in HPC and in heavily randomized GAs in particular), the modulo is cool for its speed.
Both of the above concerns can be addressed by (1) computing the (fast) modulo... of (2) rand()'s reversed bits.
Of course, the following code won't give you random numbers, but pseudo random numbers.
Use the following code
#define QUICK_RAND(m,n) m + ( std::rand() % ( (n) - (m) + 1 ) )
For example:
int myRand = QUICK_RAND(10, 20);
You must call
srand(time(0)); // Initialize random number generator.
Otherwise the numbers won't be near random.
I just found this on the Internet. This should work:
DWORD random = ((min) + rand()/(RAND_MAX + 1.0) * ((max) - (min) + 1));
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)
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.