rand and srand

  • Thread starter Bill Cunningham
  • Start date
B

Bill Cunningham

I am stumped on this one. I tried two methods and something just doesn't
seem right. I'll try my new syle.

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

main() {
srand(2000); /*seed unsigned */
printf("%u",rand());
}

Now I get a number much larger than 2000. Also when I also try RAND_MAX with
srand from time to time.

With main I was always told int was the default type and didn't need to be
declared. Main() has always worked. I hope this code is much more readable.

Bill
 
F

Falcon Kirtaran

Bill said:
I am stumped on this one. I tried two methods and something just doesn't
seem right. I'll try my new syle.

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

main() {
srand(2000); /*seed unsigned */
printf("%u",rand());
}

Now I get a number much larger than 2000. Also when I also try RAND_MAX with
srand from time to time.

With main I was always told int was the default type and didn't need to be
declared. Main() has always worked. I hope this code is much more readable.

Bill

The function rand() returns a value between 0 and RAND_MAX, not between
0 and what you pass to srand(). The latter function only sets the seed
for the random number generator (on which the next random number will be
based).

If you want to have a non-predictable sequence of random numbers, it's
often a good idea to set the seed to something that is not a literal and
will change each time the program is executed.

Additionally, if you want to generate a random number between 0 and
2000, the code to do that uses the modulus operator, thusly:

printf("%u\n", (rand() % 2001));

For one, without the \n (newline), nothing will separate your numbers
from each other. The second part of this is the % 2001. That divides
the value from rand() by 2001, and returns the remainder - so the number
can be anything from 0 to 2000. If rand() returns 2001, the modulus
makes it 0, etc.

As for your main(), I wasn't actually aware that such code was legal C.
My guess is that it is actually void main(), because you never return
a value from it, so the exit status of your program is most likely
undefined. It is a good idea, particularly in UNIX, to declare it int,
and return 0 at the end (unless the program failed).
 
S

santosh

Bill said:
I am stumped on this one. I tried two methods and something just
doesn't
seem right. I'll try my new syle.

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

main() {
srand(2000); /*seed unsigned */
printf("%u",rand());
}

Now I get a number much larger than 2000.

So what did you expect. Have you read the documentation for srand and
rand. The former "seeds" the pseudo-random number generator implemented
as rand, to start a new sequence of PRNs.
Also when I also try
RAND_MAX with srand from time to time.

That's not a very good idea. One common method is to use the return
value of the time function as the argument to srand.
With main I was always told int was the default type and didn't need
to be declared. Main() has always worked. I hope this code is much
more readable.

Well, implicit int return has been removed from the current standard,
but you'll find that almost all compilers will still tolerate code that
uses this feature. However it's always a good programming practise to
specify the return type for all your functions. It makes for *more*
readable code, not less.

Also rand returns an int value. The correct specifier for printf is %d,
not %u.
 
B

Bill Cunningham

The function rand() returns a value between 0 and RAND_MAX, not between
0 and what you pass to srand(). The latter function only sets the seed
for the random number generator (on which the next random number will be
based).

If you want to have a non-predictable sequence of random numbers, it's
often a good idea to set the seed to something that is not a literal and
will change each time the program is executed.

Additionally, if you want to generate a random number between 0 and 2000,
the code to do that uses the modulus operator, thusly:

printf("%u\n", (rand() % 2001));

For one, without the \n (newline), nothing will separate your numbers from
each other. The second part of this is the % 2001. That divides the
value from rand() by 2001, and returns the remainder - so the number can
be anything from 0 to 2000. If rand() returns 2001, the modulus makes it
0, etc.

Thanks so much for your advice. I haven't used code with modulus yet and
this is the first time I've seen it.
As for your main(), I wasn't actually aware that such code was legal C. My
guess is that it is actually void main(), because you never return a value
from it, so the exit status of your program is most likely undefined. It
is a good idea, particularly in UNIX, to declare it int, and return 0 at
the end (unless the program failed).

The C99 standard wants and int. But all the compilers I've used accept
main() and main(int argc,char *argv[]) when parameters are used. Otherwise
automatic void of course with just () as parameters. Thanks for the advice
on rand. So is there really a need to use srand ( ) ?

Bill
 
F

Falcon Kirtaran

Bill said:
The function rand() returns a value between 0 and RAND_MAX, not between
0 and what you pass to srand(). The latter function only sets the seed
for the random number generator (on which the next random number will be
based).

If you want to have a non-predictable sequence of random numbers, it's
often a good idea to set the seed to something that is not a literal and
will change each time the program is executed.

Additionally, if you want to generate a random number between 0 and 2000,
the code to do that uses the modulus operator, thusly:

printf("%u\n", (rand() % 2001));

For one, without the \n (newline), nothing will separate your numbers from
each other. The second part of this is the % 2001. That divides the
value from rand() by 2001, and returns the remainder - so the number can
be anything from 0 to 2000. If rand() returns 2001, the modulus makes it
0, etc.

Thanks so much for your advice. I haven't used code with modulus yet and
this is the first time I've seen it.
As for your main(), I wasn't actually aware that such code was legal C. My
guess is that it is actually void main(), because you never return a value
from it, so the exit status of your program is most likely undefined. It
is a good idea, particularly in UNIX, to declare it int, and return 0 at
the end (unless the program failed).

The C99 standard wants and int. But all the compilers I've used accept
main() and main(int argc,char *argv[]) when parameters are used. Otherwise
automatic void of course with just () as parameters. Thanks for the advice
on rand. So is there really a need to use srand ( ) ?

Bill

The function srand() sets the seed for the algorithm that returns the
next random number. It is highly recommended that you set it to
something or another, particularly (part of) the system time. If you
don't, the sequence will be static and not really that random at all.
 
J

Johannes Bauer

Falcon said:
Additionally, if you want to generate a random number between 0 and
2000, the code to do that uses the modulus operator, thusly:

No! It is not!

In the man mage it says

---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8----
Notes
The versions of rand() and srand() in the Linux C Library use the same
random number generator as random() and srandom(), so the lower-order
bits should be as random as the higher-order bits. However, on older
rand() implementations, and on current implementations on different
systems, the lower-order bits are much less random than the higher-order
bits. Do not use this function in applications intended to be portable
when good randomness is needed.

In Numerical Recipes in C: The Art of Scientific Computing (William H.
Press, Brian P. Flannery, Saul A. Teukolsky, William T. Vetterling; New
York: Cambridge University Press, 1992 (2nd ed., p. 277)), the following
comments are made:

"If you want to generate a random integer between 1 and 10, you
should always do it by using high-order bits, as in

j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));

and never by anything resembling

j = 1 + (rand() % 10);

(which uses lower-order bits)."
----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----

Regards,
Johannes
 
F

Flash Gordon

Falcon Kirtaran wrote, On 09/03/08 20:57:
The function rand() returns a value between 0 and RAND_MAX, not between
0 and what you pass to srand(). The latter function only sets the seed
for the random number generator (on which the next random number will be
based).

If you want to have a non-predictable sequence of random numbers, it's
often a good idea to set the seed to something that is not a literal and
will change each time the program is executed.

Additionally, if you want to generate a random number between 0 and
2000, the code to do that uses the modulus operator, thusly:

printf("%u\n", (rand() % 2001));

For one, without the \n (newline), nothing will separate your numbers
from each other. The second part of this is the % 2001. That divides
the value from rand() by 2001, and returns the remainder - so the number
can be anything from 0 to 2000. If rand() returns 2001, the modulus
makes it 0, etc.

There are issues with that method. See the comp.lang.c FAQ question
13.16 for why this is not good, and search the group for the long
debates there have been about whether the answer in the FAQ is correct.
As for your main(), I wasn't actually aware that such code was legal C.

It was legal from when C was first created, continued to be legal when C
was standardised and was only banned by the latest C standard which is
not fully supported by most compilers.
My guess is that it is actually void main(),

This is why reading a good book is generally far better than guessing.
Until C99 if the type was not specified it was implicitly assumed to be int.
because you never return a
value from it, so the exit status of your program is most likely
undefined.

It is. Well, in C99 it became specified but the OP is not using C99 and
in any case being explicit is far better practice.
It is a good idea, particularly in UNIX, to declare it int,
and return 0 at the end (unless the program failed).

Agreed. The standard even provides two macros in stdlib.h, EXIT_SUCCESS
and EXIT_FAILURE with the obvious meanings, although 0 also means
successful termination. All other return values are non-portable.
 
F

Falcon Kirtaran

Johannes said:
No! It is not!

In the man mage it says

---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8----
Notes
The versions of rand() and srand() in the Linux C Library use the same
random number generator as random() and srandom(), so the lower-order
bits should be as random as the higher-order bits. However, on older
rand() implementations, and on current implementations on different
systems, the lower-order bits are much less random than the higher-order
bits. Do not use this function in applications intended to be portable
when good randomness is needed.

In Numerical Recipes in C: The Art of Scientific Computing (William H.
Press, Brian P. Flannery, Saul A. Teukolsky, William T. Vetterling; New
York: Cambridge University Press, 1992 (2nd ed., p. 277)), the following
comments are made:

"If you want to generate a random integer between 1 and 10, you
should always do it by using high-order bits, as in

j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));

and never by anything resembling

j = 1 + (rand() % 10);

(which uses lower-order bits)."
----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----

Regards,
Johannes

You could do that too, I suppose. However, where lots of randomness is
not needed (a CGI application that returns random images), I've actually
just skipped a step and applied the modulus to the system time.
 
J

Jack Klein

[snip]
As for your main(), I wasn't actually aware that such code was legal C.

Wherever did you get that idea? That code was perfectly legal in C up
until the 1999 update to the C language standard.
My guess is that it is actually void main(), because you never return

Now you're getting silly. Prior to C99, everyplace where it was legal
to define or declare something without an explicit type, it was
implicitly typed as int. Never as void.

main()

....prior to C99, was exactly identical to:

int main()

....and is illegal under C99 and later versions, as all declarators
must explicitly declare a type.
a value from it, so the exit status of your program is most likely
undefined. It is a good idea, particularly in UNIX, to declare it int,
and return 0 at the end (unless the program failed).

This is correct under any version of the C standard. If a program
"falls off the end" of main() without returning a value, the exit
status returned to the environment is undefined.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
K

Keith Thompson

Bill Cunningham said:
I am stumped on this one. I tried two methods and something just doesn't
seem right. I'll try my new syle.

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

main() {
srand(2000); /*seed unsigned */
printf("%u",rand());
}

Now I get a number much larger than 2000. Also when I also try RAND_MAX with
srand from time to time.

You seem to be assuming that srand(2000) causes rand to return values
in the range 0 to 1999. That's incorrect. I suggest you take a few
moments to sit down and figure out just how you arrived at that
mistaken idea, and learn from it to avoid similar mistakes in the
future.

It looks to me (though I could be mistaken) that you just guessed.
That's a very bad way to determine how C standard library functions
work. (It might work better with a library with a more coherent
design, where all the design decisions actually make sense rather than
being based on random historical precedent, but even then it's a bad
idea.)

Read the documentation. It will tell you what srand() does, and what
rand() does. (It will also tell you that rand() returns an int, not
an unsigned int.)

If you want to try out a C function that you're not familiar with,
don't even *think* about writing code that uses it unless you've read
and understood the documentation first.
With main I was always told int was the default type and didn't need to be
declared. Main() has always worked. I hope this code is much more readable.

Yes, the corrected formatting makes the code much easier to read;
thank you.

As for the declaration of main, yes, most compilers will accept
"main() { ... }", but it's still a bad idea.

C89, as well as earlier pre-standard versions of the language, had an
"implicit int" rule, that many things could be declared without
specifying the type, and they would be taken to be of type int by
default. C99 (which is not yet widely implemented in full) eliminated
this rule, making "main()" illegal. But aside from whether implicit
int is allowed by a particular standard or a particular
implementation, the important point is that (with all due respect to
Dennis Ritchie), it's a *bad rule*. It's an ugly special case that
lets you save a few keystrokes but makes code harder to read.

(As I understand it, saving keystrokes was more important when C and
its ancestor languages were first designed; the teletypes of the time
required a lot more pressure to enter characters than a modern
keyboard does. That rationale has been irrelevant for many decades.)

Just because you *can* omit the "int" (sometimes), that doesn't mean
you *should*. Even ignoring the changes made in C99, if something is
of type int, you should explicitly declare it that way. And all
function declarations should be prototypes ("int main(void)" is a
prototype, "int main()" isn't).

My strong advice is that you should define main as
int main(void) { ... }
or, if you're going to use command-line arguments, as
int main(int argc, char **argv) { ... }
*and* you should explicitly return a value:

int main(void) {
/* more code here */
return 0;
}

You can get away with omitting some of these things sometimes, perhaps
most of the type, but there's no good reason why you should.
 
K

Keith Thompson

Jack Klein said:
On Sun, 09 Mar 2008 14:57:38 -0600, Falcon Kirtaran


This is correct under any version of the C standard. If a program
"falls off the end" of main() without returning a value, the exit
status returned to the environment is undefined.

No, C99 added a special-case rule that falling off the end of main()
does an implicit "return 0;"; see C99 5.1.2.2.3.
 
B

Bill Cunningham

You seem to be assuming that srand(2000) causes rand to return values
in the range 0 to 1999. That's incorrect. I suggest you take a few
moments to sit down and figure out just how you arrived at that
mistaken idea, and learn from it to avoid similar mistakes in the
future.

It looks to me (though I could be mistaken) that you just guessed.
That's a very bad way to determine how C standard library functions
work. (It might work better with a library with a more coherent
design, where all the design decisions actually make sense rather than
being based on random historical precedent, but even then it's a bad
idea.)

Read the documentation. It will tell you what srand() does, and what
rand() does. (It will also tell you that rand() returns an int, not
an unsigned int.)

------

void srand (unsigned n)

Initailizes the random number generator with the seed n. After this function
has been called calls to rand ( ) generate a new sequence of random numbers

-- "C pocket reference" by O'reilly

Maybe I misunderstood this. I thought the RAND_MAX macro went with srand
( ). Maybe then it goes to rand ( ).

Bill
 
M

Mark McIntyre

Bill said:
I am stumped on this one. I tried two methods and something just doesn't
seem right. I'll try my new syle.

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

main() {
srand(2000); /*seed unsigned */
printf("%u",rand());
}

Now I get a number much larger than 2000. Also when I also try RAND_MAX with
srand from time to time.

Read the documentation on rand, and read the documentation on srand.
They do NOT do what you think.
With main I was always told int was the default type and didn't need to be
declared.

That is called "implicit int", and has been deprecated since at least
1995. Deprecated means "you should not do it, though you can get away
with it".
 
R

Richard Heathfield

santosh said:
Bill Cunningham wrote:

The C99 standard wants and int.

Or a type compatible with int.
[...] So is there really a need to use srand ( ) ?

Yes. If you want your next pseudo-random sequence to be different and
not repeat.

The way the OP was using srand(), the next pseudo-random sequence will not
be any different. I would explain further, but there's no point - it's all
in the FAQ, in the "Library Functions" section - see http://c-faq.com
 
C

CBFalconer

Bill said:
.... snip ...


------

void srand (unsigned n)

Initailizes the random number generator with the seed n. After
this function has been called calls to rand ( ) generate a new
sequence of random numbers

-- "C pocket reference" by O'reilly

Don't snip references (the initial lines that say "joe wrote") for
any material you quote.

Such documentation is all very well for rough reminders. For
accuracy in the C library, use the C standard. There are a couple
of version listed below. The .bz2 version is pure text and needs
decompression after you get it, the other is a pdf.

--
Some useful references about C:
<http://www.ungerhu.com/jxh/clc.welcome.txt>
<http://c-faq.com/> (C-faq)
<http://benpfaff.org/writings/clc/off-topic.html>
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf> (C99)
<http://cbfalconer.home.att.net/download/n869_txt.bz2> (C99, txt)
<http://www.dinkumware.com/c99.aspx> (C-library}
<http://gcc.gnu.org/onlinedocs/> (GNU docs)
<http://clc-wiki.net/wiki/C_community:comp.lang.c:Introduction>
 
C

CBFalconer

Mark said:
.... snip ...

That is called "implicit int", and has been deprecated since at
least 1995. Deprecated means "you should not do it, though you
can get away with it".

I knew it was deprecated (in fact gone) in C99, but recently found
a .pdf of a draft for C95, and noticed it was also eliminated
there. I assumed this was a mistake, because it was a draft.

The C95 draft was n1124.pdf, found at:

http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf

Does anybody know the true facts (about C95). And is there a
descriptive file about the contents of that directory?
 
F

Falcon Kirtaran

Bill said:
------

void srand (unsigned n)

Initailizes the random number generator with the seed n. After this function
has been called calls to rand ( ) generate a new sequence of random numbers

-- "C pocket reference" by O'reilly

Maybe I misunderstood this. I thought the RAND_MAX macro went with srand
( ). Maybe then it goes to rand ( ).

Bill

It does not go to either. The only thing it represents is the highest
number rand() will return. Also, if you srand(1) in a program, the same
sequence of random numbers will be returned each time it is run on the
same implementation and platform.
 
F

Falcon Kirtaran

CBFalconer said:
Mark McIntyre wrote:
... snip ...

I knew it was deprecated (in fact gone) in C99, but recently found
a .pdf of a draft for C95, and noticed it was also eliminated
there. I assumed this was a mistake, because it was a draft.

The C95 draft was n1124.pdf, found at:

http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf

Does anybody know the true facts (about C95). And is there a
descriptive file about the contents of that directory?

Either way, it's madness not to write the four characters plus one line
it would take to do it correctly :p
 
B

Ben Pfaff

Falcon Kirtaran said:
...if you srand(1) in a program, the same sequence of random
numbers will be returned each time it is run on the same
implementation and platform.

If you don't call srand() at all, then the implementation behaves
as if srand(1) was called.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top