How does srand relate to rand function?
Asked Answered
D

4

19

I understand that rand() function generates the same number(s) each you run it if you don't change the seed number. That's where srand() comes in. Time is always changing so I know that you should pass the time(null) parameter to srand. My question is with the code below from a tutorial site.

int main()
{
    int i, n=5;
    time_t t;

    /* Intializes random number generator */
    srand((unsigned) time(&t));

    /* Print 5 random numbers from 0 to 50 */
    for( i = 0 ; i < n ; i++ ) {
        printf("%d\n", rand() % 50);
    }

    return(0);
}

I see no link from the srand

((unsigned) time(&t)); 

and rand.

printf("%d\n", rand() % 50);

Where is the connection between rand and srand? What I mean or expect is I assume rand() will get some parameter from srand() so it knows to generate different numbers each time. I assume it would look something like rand(srand(time(null));

It's like initializing a variable without using it to me. srand is being initialized, but I don't see it being used.

Does rand generate different numbers because srand is called first before rand?

Dann answered 22/1, 2014 at 3:21 Comment(1)
At the command line, you can see the documentation for these functions by typing man 3 rand and man 3 srand.Fitzgerald
M
24

The random number seed is a global static variable. rand and srand both have access to it.

Marrowbone answered 22/1, 2014 at 3:26 Comment(0)
C
16

srand() sets the seed which is used by rand to generate "random" numbers (in quotes because they're generally pseudo-random). If you don't call srand before your first call to rand, it's as if you had called srand(1) to set the seed to one.

A lot of code uses the current time as the seed so as to make each program run use a different sequence of random numbers but you can always change that to something like srand(42) during debugging, for the purposes of repeatability. And the call to time() doesn't actually need a variable to place the time in, you can just pass NULL:

srand (time (NULL));

The whole thing could be implemented in a single file with something like the following, the example given in the standard (ISO C99 7.20.2.2 The srand function).

// RAND_MAX assumed to be 32767.
static unsigned long int next = 1;
void srand(unsigned int seed) { next = seed; }
int rand(void) {
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65536) % 32768;
}

The fact that next is a static variable at the top of the file means that it's invisible to everything outside the file but visible to everything inside (sort of a localised global). That's the communication method between srand() and rand().

Chicoine answered 22/1, 2014 at 3:24 Comment(2)
I think what OP is asking is more like the implementation of these two functions.Essam
One question here - How has the standard arrived at the large numbers inside the rand() function? What is the logic behind it?Kessiah
F
5

You don't see a link because (luckily!) whoever designed rand() decided to keep that an implementation detail, in the same way as you don't see what's inside a FILE from stdio; the downside is that they decided to make that state a global (but hidden) variable rather than a parameter to the generator.

Contrast that to the deprecated rand_r(): the state is an unsigned integer (assumed to be >= 32 bits), which means that even it's forbidden to use any better generator whose state is greater than that, simply because there is no room to store it!

By keeping the internal state hidden, instead, one is free to pick whatever algorithm works best (speed, period, ...) and use it behind the scenes, as long as you guarantee that calling rand without initialization is the same as calling srand with seed==1.

Paxdiablo showed you the example from the C standard; see eg http://en.wikipedia.org/wiki/Multiply-with-carry for an example using a different generator that you could hide behind rand/srand.

Just to be extra-extra clear: had rand_r been designed properly, there would be an opaque type, say rand_t (which could be an integer, a structure, an array, ...), which you would pass to rand_r and to some hypotetical srand_r, as in

rand_t state;
srand_r(&state, 1);
n = rand_r(&state);

The rand function is exactly like this, except that there's only one state variable.

Figural answered 23/1, 2014 at 17:13 Comment(1)
I agree with you on all points. But I think OP just wanted to know how rand knows what the seed is if srand doesn't return something you pass into rand as a parameter. Even if we don't (shouldn't!) know how many bits of state there are or the exact algorithm generating the random numbers, the fact that state is needed, its lifetime exceeds that of a function call, and it is accessible to two functions is an inescapable consequence of being a seeded random number generator - there's no abstraction that won't need a static variable somewhere.Marrowbone
T
0

rand gives you a pseudo random sequence of numbers.

This number is generated by an algorithm that returns a sequence of apparently non-related numbers each time it is called. This algorithm uses a seed to generate the series, which should be initialized to some distinctive value using function srand.

srand on each call sets the pointer to some location in the list which you are getting in. If you don't call it on each attempt or give it a fix seed it will give you the same sequence. So many suggest giving the current second as seed. But if you try running your code in the same second twice, it will give you same sequence.

For every different seed value used in a call to srand, the pseudo-random number generator can be expected to generate a different succession of results in the subsequent calls to rand for further explanation

Trevatrevah answered 2/4, 2017 at 17:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.