What‘s the difference between srand(1) and srand(0)
Asked Answered
U

7

20

I just found out the hard way that srand(1) resets the PRNG of C(++) to the state before any call to srand (as defined in the reference). However, the seed 0 seems to do the same, or the state before any call to srand seems to use the seed 0. What’s the difference between those two calls or what is the reason they do the same thing?

For example this code (execute on Ideone)

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

int main() {
    for (int seed = 0; seed < 4; seed++ ) {
        printf( "Seed %d:", seed);
        srand( seed );
        for(int i = 0; i < 5; i++ )
            printf( "    %10d", rand() );
        printf( "\n");
    }
    return 0;
}

returns

Seed 0:    1804289383     846930886    1681692777    1714636915    1957747793
Seed 1:    1804289383     846930886    1681692777    1714636915    1957747793
Seed 2:    1505335290    1738766719     190686788     260874575     747983061
Seed 3:    1205554746     483147985     844158168     953350440     612121425
Unexampled answered 8/11, 2011 at 11:16 Comment(1)
Very interesting question. To my knowledge, srand does not have any "magic" value, but rand() is simply initialized to a seed of 1, and thus starts with that seed unless told something different. Which would implicitly mean that if you call srand(1), you "reset to the original state". However, the output you posted suggests that it really "magically resets" to seed 0 which you had set before, not to 1 (which, btw. my implementation does not do).Grisette
D
12

It is probably an implementation detail. The standard mandates that the random seed 1 is special, and the internal register of your specific random generator algorithm is probably zero-initialized, thus causing the same random sequence for seed(0) and seed(1). I'd even wager that the first line of your srand() implementation looks like:

if ( seed == 1 ) seed = 0;

to force standard-conformant behaviour.

Generally, the random number generators for rand() and srand() are not required to give different sequences for different seeds, but the same sequence for the same seed. So, don't rely on different seeds generating different random sequences, and you should be fine. If not, welcome to implementation-specific fun.

Domenicadomenico answered 8/11, 2011 at 11:23 Comment(2)
Actually, the code is more like if (seed == 0) seed = 1;, since the algorithm used by the GNU implementation of rand() doesn't work with a seed of zero.Stgermain
@MikeSeymour As I understood, either way is allowed.Imamate
S
21

How glibc does it:

around line 181 of glibc/stdlib/random_r.c, inside function __srandom_r

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

But that's just how glibc does it. It depends on the implementation of the C standard library.

Serenaserenade answered 8/11, 2011 at 11:44 Comment(0)
D
12

It is probably an implementation detail. The standard mandates that the random seed 1 is special, and the internal register of your specific random generator algorithm is probably zero-initialized, thus causing the same random sequence for seed(0) and seed(1). I'd even wager that the first line of your srand() implementation looks like:

if ( seed == 1 ) seed = 0;

to force standard-conformant behaviour.

Generally, the random number generators for rand() and srand() are not required to give different sequences for different seeds, but the same sequence for the same seed. So, don't rely on different seeds generating different random sequences, and you should be fine. If not, welcome to implementation-specific fun.

Domenicadomenico answered 8/11, 2011 at 11:23 Comment(2)
Actually, the code is more like if (seed == 0) seed = 1;, since the algorithm used by the GNU implementation of rand() doesn't work with a seed of zero.Stgermain
@MikeSeymour As I understood, either way is allowed.Imamate
P
7

Neither the C nor the C++ standards say much about the specifics of the implementation of rand() and srand(). The details are left almost entirely up to the implementor. The C standard requires that:

If srand is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand is called before any calls to srand have been made, the same sequence shall be generated as when srand is first called with a seed value of 1.

but it does not contain any requirement that different seeds must produce different sequences. Apparently, on your system, seeds of zero and one have the same effect. I would guess that this is to provide backwards compatibility with some piece of software that expects srand(0) to reset the PRNG to its initial state.

Presumptive answered 8/11, 2011 at 11:23 Comment(0)
C
1

If seed is set to 1, the generator is reinitialized to its initial value and produces the same values as before any call to rand or srand. Taken from the srand reference

Cooncan answered 8/11, 2011 at 11:26 Comment(0)
C
0

When reading manual pages, they all state that "If no seed value is provided, the rand() function is automatically seeded with a value of 1." This is probably why the reference page you link to states that seeding with 1 resets the state.

That the same result happens for seeding with both 0 and 1 is most likely implementation dependant, and should not be counted on happening on all platforms.

Coil answered 8/11, 2011 at 11:23 Comment(0)
S
-1

The srand() function uses the argument as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls to rand(). If srand() is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand() is called before any calls to srand() are made, the same sequence shall be generated as when srand() is first called with a seed value of 1.

Maybe useful: http://pubs.opengroup.org/onlinepubs/009695399/functions/rand.html

Sight answered 8/11, 2011 at 11:26 Comment(0)
C
-3

The reason 1 is specified is because some random number generators will get stuck at zero if the seed is set to zero. For example shift-registers and Multiplicative congruential types i.e. r(n+1) = (A * r(n))mod M.

Many C implementations use Linear Congruential r(n+1) = (A * r(n) + B) mod M, B <> 0 which don't get stuck.

Cryohydrate answered 31/7, 2016 at 7:17 Comment(1)
What does that have to do with the question?Malita

© 2022 - 2024 — McMap. All rights reserved.