2

If a program generates a few numbers using rand(), stores the last rand() result, and on repeated runs use srand(stored_seed), would this provide some shorter, but still usable random number sequence?

dronus
  • 10,774
  • 8
  • 54
  • 80
  • Even simpler question, if we store the first `rand()` value immediately after `srand`, and use that for the next run? – dronus Jun 28 '15 at 16:07
  • 1
    You know that `srand` should be run **once**, right? Do you mean the program is executed repeatedly, or `rand` is called repeatedly? – Yu Hao Jun 28 '15 at 16:08
  • Are you saying that you want to seed the random generator with the generated value every time? – Bakuriu Jun 28 '15 at 16:10
  • Yes, but only once every program run. The program will pull several values in sequence then. – dronus Jun 28 '15 at 16:12
  • 1
    High odds that it does not make any difference, rand() uses a simple LCG that already uses the last value. Try it. – Hans Passant Jun 28 '15 at 16:33
  • Depends entirely on which algorithm is used, but with any algorithm it's 100% guaranteed to be less random than using the functions properly. – Lee Daniel Crocker Jun 29 '15 at 19:24

1 Answers1

2

srand should be run exactly once. If you initialize it more than once the resulted sequence may not be so random.

A good way to initialize the PRNG is srand(time(NULL)*getpid());

alternatively you can try:

timeval t;
gettimeofday(&t, NULL);
srand((t.tv_usec/100) + (t.tv_sec/100));//getpid is optional

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 see 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. Source: link

Community
  • 1
  • 1
A B
  • 497
  • 2
  • 9
  • `srand(time(NULL))` is catastrophic if the application runs more then once a second. – dronus Jun 28 '15 at 16:14
  • 1
    Storing the seed on the other hand is very practically, eg. in case of errors or failures, one can easily debug or retry the run, if the seed is known. It would be nice if there would be some `get_seed()` function, but there isn't... – dronus Jun 28 '15 at 16:14
  • I've edited my answer. Well nothings prevent you from storing it, but it just not needed to initialize it more than once. You can use process pid coupled with the time, which should give you a different value after every run. – A B Jun 28 '15 at 16:17
  • I've discovered that you can use correlation on a map of "random numbers" in order to reverse the algorithm used and predict the next number. Real random number is generated by a source that has no logic. – Imobilis Jun 28 '15 at 17:21
  • @Malina yes, indeed is possible. This way this kind of software of algorithms are called pseudo-random. For better randomness a good solution is provided by hardware random numbers generator that use random physical(like temperature or radio waves) things for creating a good entropy. – A B Jun 28 '15 at 17:28
  • @AB Right, but it's still pseudo-random as it has logic. – Imobilis Jun 28 '15 at 18:07
  • Yes, if your application runs many times in quick succession and only uses one or a few random numbers each time, don't use rand(), use an out-of-process RNG like /dev/random. – Lee Daniel Crocker Jun 29 '15 at 19:25
  • Are you sure about using `t.tv_usec * t.tv_sec * getpid()` ? It gets 0 for every tv.sec=0 or tv_usec=0 ? – dronus Jun 29 '15 at 23:20
  • Despite that, setting `srand` with some microsecond timer should be good cool! On the other hand, I like the predictable debuging options, that a stored seed offers. Maybe it would be smart to extract `rand` from the stdlib source and add a get_seed function, this way the true seed value that `srand`would take to restore the exact state could be stored. – dronus Jun 29 '15 at 23:22
  • @dronus, you can simple use +1 on them if you consider 0 as a problem, but the true problem with any seed is the chance of collision. However an improvement that can be made is to divide them (in order to avoid potential overflow) and the sum them. By dividing them by 100 in theory you will have a collision at every 200+ days. – A B Jul 01 '15 at 19:36
  • Multiplying two numbers isn't a good idea, this heavily skews the seed towards even numbers (among other things). Since you're assuming a unix-like system, read a seed from `/dev/urandom`. – Gilles 'SO- stop being evil' Jul 01 '15 at 20:16