I am using glm::linearRand(-1.0f, 1.0f)
to generate random floating point numbers between -1
and 1
. Afterwards, I output the percentage of numbers that are positive (0.0f
or above).
std::srand(time(0)); // Give glm a new seed
uint32_t samples = 1000000000;
uint32_t positive = 0;
uint32_t negative = 0;
for (uint32_t i = 0; i < samples; i++) {
float rand = glm::linearRand(-1.0f, 1.0f);
if (rand >= 0.0f) {
positive++;
} else {
negative++;
}
}
std::cout << "positive %: " << std::setprecision(6) << ((float)positive / samples) * 100 << std::endl;
The percentage of positive numbers always ends up around 49.6%
, no matter how often I run the program (with different seeds!). If I understand floating point numbers correctly, there are equally many between -1.0f
and 0.0f
as there are between 0.0f
and 1.0f
.
So why does this program always generate more negative numbers than positive numbers?
Note this test code provided by Bob__
(result of comments exchange between him, IkarusDeveloper
and Marek R
).
This proves that rand
is not problem this time, but there is some problem with floats rounding inside of glm::linearRand
.
This is a bug in GLM. While the usual admonition about using %
with rand
is that the range doesn’t evenly divide RAND_MAX
, this code opts for the more straightforward approach of reducing rand()
modulo UINT8_MAX
, so that 255 is never produced. Every random value is ultimately derived from combining several such bytes, so 127/255=49.8% of the values will be in the upper half (here, positive).