Code Yarns ‍👨‍💻
Tech BlogPersonal Blog

The strange case of the random number generator that was not random

📅 2015-Apr-24 ⬩ ✍️ Ashwin Nanjappa ⬩ 🏷️ glibc, rand, srand ⬩ 📚 Archive

Problem

I was using the simple rand API provided by C for generating random numbers. I needed to generate m sequences of n numbers each. To my surprise, I found that two of these sequences were exactly the same!

Solution

I was using srand to seed the generation of each sequence. In the release version of my code, I was seeding it using time, which is a common practice:

srand((unsigned int) time(nullptr));

When I needed to debug the code, I needed the sequences to be reproducible, so I seeded them as:

// m sequences of n random numbers
for (int i = 0; i < m; ++i)
{
    srand(i);
    for (int j = 0; j < n; ++j)
        // Use rand() here
}

On closer observation, the sequences produced by srand(0) and srand(1) were exactly same!

This was surprising behavior. The srand man page had no information about this. It only warned that if no seed was provided, 1 would be assumed as seed:

If no seed value is provided, the rand() function is automatically seeded with a value of 1.

The problem was found by looking in the source code of GNU Libc. In the implementation of srand in the file stdlib/random_r.c lies this gem:

/* We must make sure the seed is not 0.  Take arbitrarily 1 in this case.  */
if (seed == 0)
  seed = 1;

You have got to love open source! So, seed of 0 is internally reset to 1 in the glibc implementation of srand!

So, beware of the seed you pass to srand. It might be wise to make sure that neither 0 or 1 is used as seed on Linux.

Tried with: GLibc 2.19.1 and Ubuntu 14.04


© 2022 Ashwin Nanjappa • All writing under CC BY-SA license • 🐘 @codeyarns@hachyderm.io📧