Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate random numbers uniformly over an entire range

Tags:

c++

random

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?

like image 552
anand Avatar asked Nov 13 '08 23:11

anand


People also ask

How do you generate uniformly distributed random numbers?

The Uniform Random Number block generates uniformly distributed random numbers over an interval that you specify. To generate normally distributed random numbers, use the Random Number block. Both blocks use the Normal (Gaussian) random number generator ( 'v4' : legacy MATLAB® 4.0 generator of the rng function).

What is a uniform random number generator?

It's just a random number where each possible number is just as likely as any other possible number. A fair die is a uniform random number generator for numbers between 1 and 6 inclusive.


1 Answers

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:

const int range_from  = 0; const int range_to    = 10; 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'; 

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:

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); 

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.

like image 55
Shoe Avatar answered Oct 23 '22 11:10

Shoe