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?
For C++, it can generate real float numbers within the range specified by dist
variable
#include <random> //If it doesnt work then use #include <tr1/random>
#include <iostream>
using namespace std;
typedef std::tr1::ranlux64_base_01 Myeng;
typedef std::tr1::normal_distribution<double> Mydist;
int main() {
Myeng eng;
eng.seed((unsigned int) time(NULL)); //initializing generator to January 1, 1970);
Mydist dist(1,10);
dist.reset(); // discard any cached values
for (int i = 0; i < 10; i++)
{
std::cout << "a random value == " << (int)dist(eng) << std::endl;
}
return (0);
}
rand() return a int between 0 and RAND_MAX. To get a random number between 0.0 and 1.0, first cast the int return by rand() to a float, then divide by RAND_MAX.
On some systems (Windows with VC springs to mind, currently), RAND_MAX
is ridiculously small, i. e. only 15 bit. When dividing by RAND_MAX
you are only generating a mantissa of 15 bit instead of the 23 possible bits. This may or may not be a problem for you, but you're missing out some values in that case.
Oh, just noticed that there was already a comment for that problem. Anyway, here's some code that might solve this for you:
float r = (float)((rand() << 15 + rand()) & ((1 << 24) - 1)) / (1 << 24);
Untested, but might work :-)
Take a look at Boost.Random. You could do something like this:
float gen_random_float(float min, float max)
{
boost::mt19937 rng;
boost::uniform_real<float> u(min, max);
boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > gen(rng, u);
return gen();
}
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.
If you know that your floating point format is IEEE 754 (almost all modern CPUs including Intel and ARM) then you can build a random floating point number from a random integer using bit-wise methods. This should only be considered if you do not have access to C++11's random or Boost.Random which are both much better.
float rand_float()
{
// returns a random value in the range [0.0-1.0)
// start with a bit pattern equating to 1.0
uint32_t pattern = 0x3f800000;
// get 23 bits of random integer
uint32_t random23 = 0x7fffff & (rand() << 8 ^ rand());
// replace the mantissa, resulting in a number [1.0-2.0)
pattern |= random23;
// convert from int to float without undefined behavior
assert(sizeof(float) == sizeof(uint32_t));
char buffer[sizeof(float)];
memcpy(buffer, &pattern, sizeof(float));
float f;
memcpy(&f, buffer, sizeof(float));
return f - 1.0;
}
This will give a better distribution than one using division.
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
int tmp = rand();
float f = (float)*((float*)&tmp);
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)
int tmp = rand();
float f = *((float*)&tmp);
tmp = (unsigned int)f // note float to int conversion!
tmp %= max_number;
f -= tmp;
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:
/**
* Function generates a random float using the upper_bound float to determine
* the upper bound for the exponent and for the fractional part.
* @param min_exp sets the minimum number (closest to 0) to 1 * e^min_exp (min -127)
* @param max_exp sets the maximum number to 2 * e^max_exp (max 126)
* @param sign_flag if sign_flag = 0 the random number is always positive, if
* sign_flag = 1 then the sign bit is random as well
* @return a random float
*/
float randf(int min_exp, int max_exp, char sign_flag) {
assert(min_exp <= max_exp);
int min_exp_mod = min_exp + 126;
int sign_mod = sign_flag + 1;
int frac_mod = (1 << 23);
int s = rand() % sign_mod; // note x % 1 = 0
int e = (rand() % max_exp) + min_exp_mod;
int f = rand() % frac_mod;
int tmp = (s << 31) | (e << 23) | f;
float r = (float)*((float*)(&tmp));
/** uncomment if you want to see the structure of the float. */
// printf("%x, %x, %x, %x, %f\n", (s << 31), (e << 23), f, tmp, r);
return r;
}
using this function randf(0, 8, 0)
will return a random number between 0.0 and 255.0