21

I have written a simple random number generator in C. int l is the lower bound and int u is the upper bound.

It works just fine, however I have a question regarding seeding it. If I was to run this in a loop, time(NULL) doesn't change the seed value quick enough to be able to prevent getting a consecutive series of random numbers that are exactly the same.

I'm wondering how anybody else might have approached this problem. All the examples I've found online use time(NULL) as the seed value generator.

int generateRandom(int l, int u)
{
   srand(time(NULL));

   int r = rand() % ((u - l) + 1);
   r = l + r;

   return r;
}

If I was to run these lines of code right next to each other, both Rand1 and Rand2 would be exactly the same.

printf("Rand1 = %d\n", generateRandom(10, 46));
printf("Rand2 = %d\n", generateRandom(10, 46));
Chris
  • 7,996
  • 11
  • 66
  • 98
  • 9
    Ugh! Don't name variables a simple unadorned `l`! Prefer `lb`, `lower`, `lowerbound`, ... – pmg Apr 07 '11 at 08:24

6 Answers6

30

srand(time(NULL)) should be run exactly once to intialise the PRNG. Do this in Main when the application starts.

Explanation:

A PRNG (Pseudo-Random Number Generator) generates a deterministic sequence of numbers dependent on the algorithm used. A given algorithm will always produce the same sequence from a given starting point (seed). If you don't explicitly seed the PRNG then it will usually start from the same default seed every time an application is run, resulting in the same sequence of numbers being used.

To fix this you need to seed the PRNG yourself with a different seed (to give a different sequence) each time the application is run. The usual approach is to use time(NULL) which sets the seed based on the current time. As long as you don't start two instances of the application within a second of each other, you'll be guaranteed a different random sequence.

There's no need to seed the sequence each time you want a new random number. And I'm not sure about this, but I have the feeling that depending on the PRNG algorithm being used re-seeding for every new number may actually result in lower randomness in the resulting sequence.

Amit
  • 45,440
  • 9
  • 78
  • 110
Andrew Cooper
  • 32,176
  • 5
  • 81
  • 116
  • 2
    At least, reseeding will not help in the quality, even if it did not hurt. Which it does, at least if seeding from `time(NULL)` every time. – Sami J. Lehtinen Apr 07 '11 at 01:46
8

Seed once at the beginning of main. If you reseed too quickly during the same second, you will end up getting the same numbers.

jonsca
  • 10,218
  • 26
  • 54
  • 62
7

srand( (unsigned) time(NULL) * getpid());

yields a more diverse random set (on OSX 10.8), including on short cycle tests.

user2608735
  • 71
  • 1
  • 2
  • 1
    If you are on OS X 10.8 and care about randomness, you should use `arc4random()` or `arc4random_uniform()`. – dreamlax Jul 23 '13 at 01:00
5

Don't seed it every time, only at the beginning of your program.

Also, many books advice against using the C-lib standard random functions. If you need good pseudo-random numbers, there's a good algorithm in Press et al., Numerical Recipes, 3rd. Edition.

Sami J. Lehtinen
  • 1,039
  • 6
  • 9
  • 2
    Be careful of NR though, the license terms for the code in the book are pretty onerous, the edition I have basically forbids any sort of version control or network file storage if you type it up! – Flexo Sep 17 '11 at 13:24
4

I assume you call the generateRandom function from another function, main or something.

If you declare the seed inside the function, you'll reset the function. Resetting the function, will make the same numbers appear several times, the same second.

Moving srand(time(NULL)); to main function will solve the problem.

Ragnar123
  • 5,174
  • 4
  • 24
  • 34
1

If you are using different processes, use (rand()+getpid())%range; I use it to test the same program with random values many times a second (If you make rand numbers, exit the program and run again very fast, the numbers will be the same)

Flexo
  • 87,323
  • 22
  • 191
  • 272
Henrique Rocha
  • 411
  • 5
  • 13