Velocity Reviews > srand(time(NULL))

# srand(time(NULL))

Ioannis Vranos
Guest
Posts: n/a

 03-10-2008
Regarding C95:

Is srand(time(NULL)); an effective solution for seeding rand(), or is
there any better approach?

Mark Bluemel
Guest
Posts: n/a

 03-10-2008
Ioannis Vranos wrote:
> Regarding C95:
>
>
> Is srand(time(NULL)); an effective solution for seeding rand(), or is
> there any better approach?

There's some discussion in this area in section 13 of the C FAQ
(http://www.c-faq.com). Try Question 13.17

Mark Bluemel
Guest
Posts: n/a

 03-10-2008
Ioannis Vranos wrote:
> Regarding C95:
>
>
> Is srand(time(NULL)); an effective solution for seeding rand(), or is
> there any better approach?

"seeding a random number generator", many of which look helpful.

Richard Bos
Guest
Posts: n/a

 03-10-2008
Ioannis Vranos <(E-Mail Removed)> wrote:

> Is srand(time(NULL)); an effective solution for seeding rand(),

Unless your time_t is a floating point type and the current time is
larger than UINT_MAX (not likely, in particular the first part);
as long as you don't call it more than once every time_t tick;
and as long as your rand() is at least of semi-reasonable quality (i.e.,
successive seeds don't lead to similar series), it's fine.

Richard

Ben Pfaff
Guest
Posts: n/a

 03-10-2008
Ioannis Vranos <(E-Mail Removed)> writes:

> Is srand(time(NULL)); an effective solution for seeding rand(), or is
> there any better approach?

By default, the C random number generator produces the same
sequence every time the program is run. In order to generate
different sequences, it has to be "seeded" using srand() with a
unique value. The function below to do this is carefully
designed. It uses time() to obtain the current time; the
alternative clock() is a poor choice because it measures CPU time
used, which is often more or less constant among runs. The
actual value of a time_t is not portable, so it computes a "hash"
of the bytes in it using a multiply-and-add technique. The
factor used for multiplication normally comes out as 257, a prime
and therefore a good candidate.

References: Knuth, _The Art of Computer Programming, Vol. 2:
Seminumerical Algorithms_, section 3.2.1; Aho, Sethi, and Ullman,
_Compilers: Principles, Techniques, and Tools_, section 7.6.

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

/* Choose and return an initial random seed based on the current time.
Based on code by Lawrence Kirby <(E-Mail Removed)>.
Usage: srand (time_seed ()); */
unsigned
time_seed (void)
{
time_t timeval; /* Current time. */
unsigned char *ptr; /* Type punned pointed into timeval. */
unsigned seed; /* Generated seed. */
size_t i;

timeval = time (NULL);
ptr = (unsigned char *) &timeval;

seed = 0;
for (i = 0; i < sizeof timeval; i++)
seed = seed * (UCHAR_MAX + 2u) + ptr[i];

return seed;
}

--
"It wouldn't be a new C standard if it didn't give a
new meaning to the word `static'."
--Peter Seebach on C99

Ioannis Vranos
Guest
Posts: n/a

 03-10-2008
Richard Bos wrote:
> Ioannis Vranos <(E-Mail Removed)> wrote:
>
>> Is srand(time(NULL)); an effective solution for seeding rand(),

>
> Unless your time_t is a floating point type

The function prototype of srand() is

void srand(unsigned int seed);

Whatever time_t is, isn't there an implicit conversion to unsigned?

> and the current time is
> larger than UINT_MAX (not likely, in particular the first part);

If the value is larger than UINT_MAX, doesn't the argument seed just
wrap around?

Ioannis Vranos
Guest
Posts: n/a

 03-10-2008
The FAQ mentions:

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

srand((unsigned int)time((time_t *)NULL));

I think the casting of NULL to "time_t *" is unnecessary in C, since
NULL can be assigned to any pointer type without casting (also the
conversion of void * to whatever_type * is implicit).

Also since the srand() function protype is

void srand(unsigned int seed);

I think the casting of the return value of time() to unsigned int is
unnecessary, since the return value is implicitly converted to the
unsigned int argument.

Richard Bos
Guest
Posts: n/a

 03-10-2008
Ioannis Vranos <(E-Mail Removed)> wrote:

> Richard Bos wrote:
> > Ioannis Vranos <(E-Mail Removed)> wrote:
> >
> >> Is srand(time(NULL)); an effective solution for seeding rand(),

> >
> > Unless your time_t is a floating point type

>
> The function prototype of srand() is
>
> void srand(unsigned int seed);
>
> Whatever time_t is, isn't there an implicit conversion to unsigned?

Yes. But the conversion of a floating point value to an integral type
causes UB if that value, rounded down, would not fit into the integral
type - even if it's an unsigned type.

> > and the current time is
> > larger than UINT_MAX (not likely, in particular the first part);

>
> If the value is larger than UINT_MAX, doesn't the argument seed just
> wrap around?

You'd think so, but no, not on conversion from a floating point value.

At least, not in C90. I haven't looked up whether this remains true in
C99.

Richard

Ben Pfaff
Guest
Posts: n/a

 03-10-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) (Richard Bos) writes:

> Ioannis Vranos <(E-Mail Removed)> wrote:
>> Richard Bos wrote:
>> > Ioannis Vranos <(E-Mail Removed)> wrote:
>> >> Is srand(time(NULL)); an effective solution for seeding rand(),
>> > Unless your time_t is a floating point type

>> The function prototype of srand() is
>>
>> void srand(unsigned int seed);
>>
>> Whatever time_t is, isn't there an implicit conversion to unsigned?

> Yes. But the conversion of a floating point value to an integral type
> causes UB if that value, rounded down, would not fit into the integral
> type - even if it's an unsigned type.

Additionally, a floating point time value may not be useful as a
random seed, for example if the time value is always between 0
and 1. (I am not aware of any systems that do this.)
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1utchar(a[i&15]);break;}}}

Eric Sosman
Guest
Posts: n/a

 03-10-2008
Ioannis Vranos wrote:
> The FAQ mentions:
>
> #include <stdlib.h>
> #include <time.h>
>
> srand((unsigned int)time((time_t *)NULL));
>
>
> I think the casting of NULL to "time_t *" is unnecessary in C, since
> NULL can be assigned to any pointer type without casting (also the
> conversion of void * to whatever_type * is implicit).
>
>
> Also since the srand() function protype is
>
> void srand(unsigned int seed);
>
>
> I think the casting of the return value of time() to unsigned int is
> unnecessary, since the return value is implicitly converted to the
> unsigned int argument.

"Unnecessary" is not always the same as "undesirable" --
do you use indentation to indicate block nesting? -- and the
question of whether to use or omit these casts is in some
degree a matter of taste. Myself, I'd omit them. Yet the
Ten Commandments For C Programmers takes the opposite view
(Third Commandment), so I am probably in a state of sin.

--
(E-Mail Removed)