Generate random numbers uniformly over an entire range
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.
How to generate a number in arbitrary range using random()={0..1} preserving uniformness and density?
If you really want to generate all possible floating point numbers in a given range with uniform numeric density, you need to take into account the floating point format. For each possible value of your binary exponent, you have a different numeric density of codes. A direct generation method will need to deal with this explicitly, and an indirect generation method will still need to take it into account. I will develop a direct method; for the sake of simplicity, the following refers exclusively to IEEE 754 single-precision (32-bit) floating point numbers.
The most difficult case is any interval that includes zero. In that case, to produce an exactly even distribution, you will need to handle every exponent down to the lowest, plus denormalized numbers. As a special case, you will need to split zero into two cases, +0 and -0.
In addition, if you are paying such close attention to the result, you will need to make sure that you are using a good pseudorandom number generator with a large enough state space that you can expect it to hit every value with near-uniform probability. This disqualifies the C/Unix rand()
and possibly the*rand48()
library functions; you should use something like the Mersenne Twister instead.
The key is to dissect the target interval into subintervals, each of which is covered by different combination of binary exponent and sign: within each subinterval, floating point codes are uniformly distributed.
The first step is to select the appropriate subinterval, with probability proportional to its size. If the interval contains 0, or otherwise covers a large dynamic range, this may potentially require a number of random bits up to the full range of the available exponent.
In particular, for a 32-bit IEEE-754 number, there are 256 possible exponent values. Each exponent governs a range which is half the size of the next greater exponent, except for the denormalized case, which is the same size as the smallest normal exponent region. Zero can be considered the smallest denormalized number; as mentioned above, if the target interval straddles zero, the probability of each of +0 and -0 should perhaps be cut in half, to avoid doubling its weight.
If the subinterval chosen covers the entire region governed by a particular exponent, all that is necessary is to fill the mantissa with random bits (23 bits, for 32-bit IEEE-754 floats). However, if the subinterval does not cover the entire region, you will need to generate a random mantissa that covers only that subinterval.
The simplest way to handle both the initial and secondary random steps may be to round the target interval out to include the entirety of all exponent regions partially covered, then reject and retry numbers that fall outside it. This allows the exponent to be generated with simple power-of-2 probabilities (e.g., by counting the number of leading zeroes in your random bitstream), as well as providing a simple and accurate way of generating a mantissa that covers only part of an exponent interval. (This is also a good way of handling the +/-0 special case.)
As another special case: to avoid inefficient generation for target intervals which are much smaller than the exponent regions they reside in, the "obvious simple" solution will in fact generate fairly uniform numbers for such intervals. If you want exactly uniform distributions, you can generate the sub-interval mantissa by using only enough random bits to cover that sub-interval, while still using the aforementioned rejection method to eliminate values outside the target interval.
Modifying the range of a uniform random number generator
ok I had to think about it for a while but it is actually not that hard. Imagine instead of rand5 you had rand2 which either outputs 0 or 1. You can make rand2 our of rand5 by simply doing
rand2() {
if(rand5() > 2.5) return 1
else return 0
}
now using rand2 multiple times do a tree to get rand7. For example if you start rand7 can be in [1,2,3,4,5,6,7] after a throw of rand2 which gives 0 you now subset to [1,2,3,4] and after another throw or rand2 which is 1 you subset to [3,4] and a final throw of 1 gives the output of rand7 to be 4. In general this tree trick can work to take a rand2 and map to randx where x is any integer.
How to generate uniformly distributed random floating point numbers on entire possible range in matlab
(Why in the name of god and little green apples would you do this in a loop?)
My point is, do it using the capabilities of MATLAB. Learn to use vectors and arrays. Apply operations to an entire array of numbers. This is how a tool like MATLAB shines. Until you do, you might as well be using a lower level language, but without the speed benefits gained from using that lower level tool.
Ok, rant over, so how do we attack this problem?
Generate each number using THREE different random values.
- A random sign
- A random exponent
- A random mantissa
Do it all using vector ops.
numtogenerate = 20000;
% the sign
S = (rand(numtogenerate,1) < 0.5)*2 - 1;
% The exponent
E = floor(rand(numtogenerate,1)*256) - 128;
% The mantissa
M = rand(numtogenerate,1)*2 - 2^-23;
% bring it all together
R = S.*M.*2.^E;
Do they cover the entire range? It seems so.
min(abs(R))
ans =
7.44202895026248e-41
max(R)
ans =
3.17337113940593e+38
min(R)
ans =
-3.3810631675676e+38
Assuming I got the ranges correct for each part, this should essentially generate every possible value in the desired range.
By the way, these are NOT uniformly distributed numbers, at least NOT in the way that term is usually applied in mathematics.
Related Topics
If You Shouldn't Throw Exceptions in a Destructor, How to Handle Errors in It
What Is External Linkage and Internal Linkage
Meaning of 'Const' Last in a Function Declaration of a Class
What Are the Barriers to Understanding Pointers and What Can Be Done to Overcome Them
Implicit Type Conversion Rules in C++ Operators
Overloading Friend Operator≪≪ For Template Class
C++ Unordered_Map Using a Custom Class Type as the Key
How to Iterate Over the Elements of an Std::Tuple
In What Cases Do I Use Malloc And/Or New
"Unpacking" a Tuple to Call a Matching Function Pointer
In C++, What Is a Virtual Base Class
Order of Evaluation in C++ Function Parameters
How to Read an Entire File into a Std::String in C++
Convert Char to Int in C and C++
How to Align Text to the Right Using Cout
Why Must a Short Be Converted to an Int Before Arithmetic Operations in C and C++
How to Properly Overload the ≪≪ Operator For an Ostream