Search code examples
c++randomglm-math

`glm::linearRand(-1.0f, 1.0f)`, gives more negative numbers than positive. Why is that? `rand` seems ok


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.


Solution

  • 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).