0

Today, I noticed that the same random number is being generated every time in a specific part of a program I am working on. My assumption was that it wasn't getting seeded properly, but it appears that it is.

I reduced the issue down to the simplest code possible. Here it is:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int main()
{
    srand(time(0));
    printf("%d\n", rand() % 49);
    
    return 0;
}

Every time I run this program, it prints the number 13. If I change the 49 the random number is getting mod-ed by to a 50 or a 48, I get a random sequence as expected (by running the program repeatedly). However, my program (the real one, not the example above) relies on an asset that for the time-being will always cause the variable that rand() is mod-ed by to be 49.

Am I missing something or doing something incorrectly? Is there something wrong with the hardware device on my processor that generates pseudo-random numbers? How can I get my program to generate a different random number (one that does not divide by 49 with a remainder of 13) each time?

EDIT: I recognize that time(0) only changes once per second. I have run this program multiple times and not in the same second, so that is not the issue. I am running on macOS. The result is the same whether I compile with gcc-11 (from Homebrew) or clang. Turning optimizations on or off has no effect.

I tried running the program a few times without the modulo to generate a sequence. Here are the numbers that were generated: 862706704, 862723511, 862740318, 862757125, 862773932, 862824353. Those all happen to divide by 49 to leave a remainder of 13.

tedtanner
  • 577
  • 6
  • 19
  • "*If I change the 49 the random number is getting mod-ed by to a 50 or a 48*". Can you please clarify that sentence. The grammar of the second part of the sentence (specifically "by to a") seems off so it is not clear what you are saying. What are you changing 49 to and what was the result? – kaylum May 10 '22 at 04:45
  • 1
    I mean that if I replace the 49 with a 50 or a 48, I get a random sequence of numbers. But if I change it back to 49, the program always prints 13. – tedtanner May 10 '22 at 04:48
  • 3
    are you on macOS? Then it's a duplicate of [Why does rand() % 7 always return 0?](https://stackoverflow.com/q/7866754/995714), [Rand() % 14 only generates the values 6 or 13](https://stackoverflow.com/q/20263187/995714), [Why is (rand() % anything) always 0 in C++?](https://stackoverflow.com/q/2129705/995714) – phuclv May 10 '22 at 04:50
  • I have run this example program multiple different times throughout an hour. It is not getting seeded with the same time. – tedtanner May 10 '22 at 04:50
  • @tedtanner If that is actually the result then something very off would be happening. What do you get if you don't mod at all? Does that show changing numbers that would result in 13 when modded with 49? – kaylum May 10 '22 at 04:51

1 Answers1

0

It appears that this question duplicates this one. Essentially, the issue is a the random number generator is a Linear Congruential Generator.

I can get some better results by xor-ing something changing (like the time) by rand() before mod-ing.

I, for one, have learned from this experience to be even more wary of pseudo-random number generators than I already was.

tedtanner
  • 577
  • 6
  • 19
  • Thanks go to @phuclv who pointed this out in a comment on the original post. – tedtanner May 10 '22 at 05:06
  • 1
    This particular generator is purely multiplicative and dates back to the 1950’s. It uses a multiplier of 16807 == 7^5, hence the outcomes are always evenly divisible by 49 regardless of the seed value. Don’t combine a purely multiplicative generator with modulo arithmetic. *Much* better generators have been developed since then, `rand()` is kept around principally for legacy reasons and should be avoided. – pjs May 10 '22 at 13:20