0

I'm implementing a basic program which generate 2 random number. The problem is the result of first number looks like it is following some kind of pattern, but the second still looks right.

Output:

6584 679
6587 1427
6591 9410
6594 156
7733 3032
7737 3780

This is my code:

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

int main(){
    srand(time(NULL));
    int a = rand()%10001, b= rand()%10001;
    printf("%d %d", a,b);

    return 0;
}

So what is the problem here and how to fix it.

Any help would be appreciated.


I am using windows 10 64 bits, gcc 8.1.0.

Steven
  • 27
  • 4
  • 1
    How are you running the program to get the multiple outputs you are showing above? – user17732522 Mar 01 '22 at 08:22
  • 1
    Your code is only printing one pair of `a, b`. I suppose that you are calling the programme several times in a row, with similar values of `time(NULL)` . What happens if you use a loop inside the code? – Damien Mar 01 '22 at 08:23
  • 1
    He re-run multiple times to get that output. – Becker Mar 01 '22 at 08:24
  • @Damien I have tried what you said then the program works well. So why the code only works with `for` loop? – Steven Mar 01 '22 at 08:29
  • 2
    When making tests, try to output the value of `time(NULL)` which initialises the random process. Similar values may lead to similar values of first numbers generated. – Damien Mar 01 '22 at 08:32
  • 3
    The seed values `time(NULL)` are too similar between runs. Use another seed value like: `int t = time(NULL); t = t ^ (t >> 5) ^ (t << 12); srand(t);`. But anyway, be aware that `time` returns the time in seconds, so between two runs within the same second, `time` will return the same value, and you'll get the same sequence of pseudo random numbers. – Jabberwocky Mar 01 '22 at 08:34
  • @Damien and why the `time(NULL)` just affect the first number, and the second still ok? – Steven Mar 01 '22 at 08:36
  • [butterfly effect](https://en.wikipedia.org/wiki/Butterfly_effect). A small difference at the beginning will provide a large difference at the end. – Damien Mar 01 '22 at 08:38

1 Answers1

1

time(NULL) value acts as the same seed value every time you run the program. The reason behind that your CPU will generate a similar starting NULL time for every time. To get rid of this kind of effect you need to play with the seed value, so that even if your computer starts with the same time(NULL) value, it needs to get seed different than the other runs. For that purpose, you can simply do the following:

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


int main(){
    srand((unsigned)time(NULL) * (unsigned)getpid());

    int a = rand()%10001, b= rand()%10001;
    printf("%d %d", a,b);


    return 0;
}

Full credit to @pmg, thanks for the comments to improve the solution.

  • 1
    Yes, you are right. I updated the solution without UB. If someone is interested in sequence point, here is the [link](https://stackoverflow.com/questions/3575350/sequence-points-in-c). – BGForDevelopers Mar 01 '22 at 08:53
  • 2
    Maybe you meant something like `srand((unsigned)time(NULL) * (unsigned)getpid())`... your proposed change just squares the return value from `time()`; if it's in the same second, it's still the same value. – pmg Mar 01 '22 at 08:58
  • Your solution may be more reliable since the process id will differ for every run. Let me update the solution. – BGForDevelopers Mar 01 '22 at 09:45
  • 1
    Because `getpid()` is not defined by the Standard, maybe you want to `#include` one of `` or `` according to whether `_WIN32` is defined :-) – pmg Mar 01 '22 at 09:56
  • 2
    `(unsigned)time(NULL) * (unsigned)getpid()` is biased. Example, 75% of the time the LSBit is 0 - only odd * odd is odd. Instead use `(unsigned)time(NULL) ^ (unsigned)getpid()`. – chux - Reinstate Monica Mar 01 '22 at 15:57