views:

6446

answers:

7
+6  Q: 

C++ random float

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?

+16  A: 

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.

rlbond
+14  A: 

This will generate a number from 0.0 to 1.0, inclusive.

float r = (float)rand()/(float)RAND_MAX;

Note that the rand() function will often not be sufficient if you need truly random numbers.

John Dibling
Don't forget to seed first!
Klaim
Best to note that the both limits are inclusive.
dmckee
Also the system rand() is usually fairly primitive, and not a good idea for many applications---look at the many SO questions on random number generators for details...
dmckee
A: 

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.

James Curran
+9  A: 

call the code with two float values,the code works in any range.

float rand_FloatRange(float a, float b)
{
return ((b-a)*((float)rand()/RAND_MAX))+a;
}
John
+6  A: 

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

Joey
Looks like a nice solution.
Trap
What about float r = (float)((rand() << 9) | rand()) / RAND_MAX? (also untested)
Trap
Argh, sorry, dividing by RAND_MAX won't take you anywhere ... the whole point of this trick was to have something that's larger than RAND_MAX ... fixed that for me as well.
Joey
Be careful about composing random numbers without theory... consecutive calls to rand() might not be completely independent. Hint: if its a linear congruential generator, watch the low bit on consecutive calls: it alternates between 0 and 1.
RBerteig
I know. For some applications this might be enough, though. But yes, you should probably use more than just two calls in this case. There is no silver bullet in this case, you can't even rely on it being an LCG. Other PRNGs have weak high bits. The Boost solution should be the best here.
Joey
(nb: The low bit returned by rand in MSVC isn't the lowest bit of the RNG state. For 100 rand() calls I get the following: 1100100000111111101010010010011010101110110110111010011111100100000000010100011011000000100101100011. Java uses a 48-bit LCG and only uses 32 bits, VC seems to do it similarly)
Joey
A: 

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.

//Returns a random number in the range [0.0f, 1.0f).  Every
//bit of the mantissa is randomized.
float rnd(void){
  //Generate a random number in the range [0.5f, 1.0f).
  unsigned int ret = 0x3F000000 | (0x7FFFFF & ((rand() << 8) ^ rand()));
  unsigned short coinFlips;

  //If the coin is tails, return the number, otherwise
  //divide the random number by two by decrementing the
  //exponent and keep going. The exponent starts at 63.
  //Each loop represents 15 random bits, a.k.a. 'coin flips'.
  #define RND_INNER_LOOP() \
    if( coinFlips & 1 ) break; \
    coinFlips >>= 1; \
    ret -= 0x800000
  for(;;){
    coinFlips = rand();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    //At this point, the exponent is 60, 45, 30, 15, or 0.
    //If the exponent is 0, then the number equals 0.0f.
    if( ! (ret & 0x3F800000) ) return 0.0f;
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
  }
  return *((float *)(&ret));
}
iNFiNiTyLoOp
interesting approach, I'd like to upvote but, I really don't understand what's going on
hasen j
+1  A: 

If you are using C++ and not C, then remember that in technical report 1 (TR1) and in the C++0x draft they have added facilities for a random number generator in the header file, I believe it is identical to the Boost.Random library and definitely more flexible and "modern" than the C library function, rand.

This syntax offers the ability to choose a generator (like the mersenne twister mt19937) and then choose a distribution (normal, bernoulli, binomial etc.).

Syntax is as follows (shameless borrowed from this site):

  #include <iostream>
  #include <random>

  ...

  std::tr1::mt19937 eng;  // a core engine class 
  std::tr1::normal_distribution<float> dist;     

  for (int i = 0; i < 10; ++i)        
      std::cout << dist(eng) << std::endl;
Rick