How do I generate random floats in C++?
I thought I could take the integer rand and divide it by something, would that be adequate enough?
How do I generate random floats in C++?
I thought I could take the integer rand and divide it by something, would that be adequate enough?
I wasn't satisfied by any of the answers so far so I wrote a new random float function. It makes bitwise assumptions about the float data type. It still needs a rand() function with at least 15 random bits.
rand()
can be used to generate pseudo-random numbers in C++. In combination withRAND_MAX
and a little math, you can generate random numbers in any arbitrary interval you choose. This is sufficient for learning purposes and toy programs. If you need truly random numbers with normal distribution, you'll need to employ a more advanced method.This will generate a number from 0.0 to 1.0, inclusive.
This will generate a number from 0.0 to some arbitrary
float
,X
:This will generate a number from some arbitrary
LO
to some arbitraryHI
:Note that the
rand()
function will often not be sufficient if you need truly random numbers.Before calling
rand()
, you must first "seed" the random number generator by callingsrand()
. This should be done once during your program's run -- not once every time you callrand()
. This is often done like this:In order to call
rand
orsrand
you must#include <cstdlib>
.In order to call
time
, you must#include <ctime>
.Completely random valid float number is generated in the following way: Random sign, random exponent and random mantissa. Here is an example of generating random numbers from 0..MAXFLOAT with uniform distribution:
Important Note: RAND_MAX is by default equal to 2^16 (on 32bits systems) so rand() can generate at most 15 random bits. Since floating point has total of 32 bits we must activate the rand() at least 3 times to generate random 32 bits. I used 8 bits of rand() to generate Exponent and another 2 calls to rand() to generate 23 bits of mantissa.
Common mistake to avoid: If you use
(float)rand()/MAX_RAND
to obtain a floating point in range [0..1], You will still get random numbers in uniform distribution but of low precision. For example your random generator can generate 0.00001 and 0.00002 but cannot generate 0.000017. Such random is 256 times less precise than the actual floating point representation.Optimization: My function is not optimized for speed. You can improve it by replacing '%' division with bitwise logical operations. For example Instead of
%256
use&0xFF
In my opinion the above answer do give some 'random' float, but none of them is truly a random float (i.e. they miss a part of the float representation). Before I will rush into my implementation lets first have a look at the ANSI/IEEE standard format for floats:
|sign (1-bit)| e (8-bits) | f (23-bit) |
the number represented by this word is (-1 * sign) * 2^e * 1.f
note the the 'e' number is a biased (with a bias of 127) number thus ranging from -127 to 126. The most simple (and actually most random) function is to just write the data of a random int into a float, thus
note that if you do
float f = (float)rand();
it will convert the integer into a float (thus 10 will become 10.0).So now if you want to limit the maximum value you can do something like (not sure if this works)
but if you look at the structure of the float you can see that the maximum value of a float is (approx) 2^127 which is way larger as the maximum value of an int (2^32) thus ruling out a significant part of the numbers that can be represented by a float. This is my final implementation:
using this function
randf(0, 8, 0)
will return a random number between 0.0 and 255.0In modern
c++
you may use the<random>
header that came withc++11
.To get random
float
's you can usestd::uniform_real_distribution<>
.You can use a function to generate the numbers and if you don't want the numbers to be the same all the time, set the engine and distribution to be
static
.Example:
It's ideal to place the
float
's in a container such asstd::vector
:Example output:
Take a look at Boost.Random. You could do something like this:
Play around, you might do better passing the same mt19937 object around instead of constructing a new one every time, but hopefully you get the idea.