Question

As shown in this post there are a few ways to generate random floats in c++. But I don't fully understand the 3rd option of the answer:

float r3 = LO + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(HI-LO)));

Can someone explain this line to me? How are the limits calculated here?

Was it helpful?

Solution

rand() generates random numbers from 0 to RAND_MAX.

0 <= rand()/RAND_MAX <= 1    
implies: 0 <= rand()/RAND_MAX*(HI-LO) <= HI-LO    
implies: LO <= LO + rand()/RAND_MAX*(HI-LO) <= HI

Now since RAND_MAX and HI-LO are integers, RAND_MAX/(HI-LO) is typecasted to float.

OTHER TIPS

rand() returns something between 0 and RAND_MAX. Let's call it r.

r / (RAND_MAX/(HI-LO)) = r / RAND_MAX * (HI-LO) so this is between 0 and HI-LO.

Add LO and you have a value between LO and HI

The static_casts force the compiler to convert to float, else it will stick to ints and mess the computation.

Mr STL explained why that (and other rand() related constructs) are a very bad idea in his presentation "rand() considered harmful".

The idea behind that code is to use floating point to reduce the entropy loss of a random number clamped by a modulo operation.
As Stephen points out, the floating point solution has not the problem which the modulo operation introduces (Basically there is an interval of values which have more probability to be generated than the others, thanks to the modulo, breacking the theorical uniformity of rand()).
But floating-point introduces a new problem: The rounding produced at the final conversion from float type to the integral type the user expects leads to the problem that the same number is generated many times for different inputs, but a few values are generated only by one. So, again, the uniformity is lost. Of course that rounding is not a problem if the goal is to generate a random floating-point, as in your case. But the roundings and divisions performed could lead to break the uniformity of the distribution too.

The conclusion to all of the menctioned above is: That code tries to solve the uniformity problems of the classic modulo way, but leads to (less? I'm not sure) uniformity problems too. So try to replace C random facilities with other libraries (Like the standard <random> library provided since C++11).

It is attempting to generate a random number in the range [LO, HI]

A better way to do it in C++11 is to use the <random> library:

std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(LO,HI);
double value = distribution(generator);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top