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
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.
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);
}
I just found this on the Internet. This should work:
DWORD random = ((min) + rand()/(RAND_MAX + 1.0) * ((max) - (min) + 1));
I'd like to complement Angry Shoe's and peterchen's excellent answers with a short overview of the state of the art in 2015:
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 (http://www.pcg-random.org/) provides many interesting articles about the theme of random number generation in general and the C++ library in particular.
Boost.Random
(documentation) is the library which inspired C++11
's <random>
, with whom 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:
random_device
uses system-specific methods to offer seeding of good qualityThe 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:
mt19937
a thread_local
: the generator is quite plump (> 2 KB) and is better not allocated on the stackmt19937
with more than one integer: the Mersenne Twister has a big state and can take benefit of more entropy during initialization 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 esoterical 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.
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. Only defect, 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.
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.
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 and 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();
}
Of course, the following code won't give you random numbers but pseudo random number. 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.