Random is strange

J

Jenny

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int roll(void);

enum status {CONTINUE, WIN, LOST};

int main()
{

int sum, mypoint;
enum status result;


sum = roll();

if( sum == 7|| sum == 11)
result = WIN;
else if( sum == 2 ||sum == 3||sum == 12)
result = LOST;
else
result = CONTINUE;

mypoint = sum;


while(result == CONTINUE){

sum = roll();

if(sum == mypoint)
result = WIN;
else if(sum == 7)
result = LOST;
else
result = CONTINUE;
}

if( result == WIN)
printf("The player win\n", result);
if( result == LOST)
printf("The player lost\n", result);
return 0;
}


int roll(void)
{
int die1, die2;
srand(time(NULL));
die1 = rand() % 6 + 1;
die2 = rand() % 6 + 1;
printf("Player rolled %d + %d = %d\n", die1, die2, die1 + die2);
return die1 + die2;
}
Good afternoon, everyone. I'm Kate.I am curious about where to place
the sentence:
srand ( time ( NULL ) );
In this program, if I place it in function ------- int roll
( void ) ,I always get a wrong result, such as:
4 + 1 = 5; 4 + 5 = 9;
4 + 1 = 5; 4 + 5 = 9
The player win. The player
win.
Press any key to continue. Press any key to
continue.
The player can win every time.

But if I place the sentence in function ------- int main (), the
program executes successfully.
I don't quite understand .Can you help me ?
 
M

maverik

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int roll(void);

enum status {CONTINUE, WIN, LOST};

int main()
{

        int sum, mypoint;
        enum status result;

        sum = roll();

        if( sum == 7|| sum == 11)
                result = WIN;
        else if( sum == 2 ||sum == 3||sum == 12)
                result = LOST;
        else
                result = CONTINUE;

        mypoint = sum;

        while(result == CONTINUE){

                sum = roll();

           if(sum == mypoint)
              result = WIN;
                  else if(sum == 7)
              result = LOST;
                   else
              result = CONTINUE;
        }

        if( result == WIN)
            printf("The player win\n", result);
                if( result == LOST)
            printf("The player lost\n", result);
return 0;

}

int roll(void)
{
        int die1, die2;
        srand(time(NULL));
        die1 = rand() % 6 + 1;
        die2 = rand() % 6 + 1;
        printf("Player rolled %d + %d = %d\n", die1, die2, die1 + die2);
return die1 + die2;}

Ok, if you read man you should see some notes says that you shouldn't
use constructions like that:
die1 = rand() % 6 + 1;

Use

die1 = 1.0 + (int) (6.0 * rand() / (RAND_MAX + 1.0));

or something like that (that uses high bits).

HTH
 
N

Nick Keighley

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int roll(void);

enum status {CONTINUE, WIN, LOST};

int main()

int main (void)
is better style
{
        int sum, mypoint;
        enum status result;

        sum = roll();

        if( sum == 7|| sum == 11)
                result = WIN;
        else if( sum == 2 ||sum == 3||sum == 12)
                result = LOST;
        else
                result = CONTINUE;

        mypoint = sum;

        while(result == CONTINUE){

                sum = roll();

           if(sum == mypoint)
              result = WIN;
                  else if(sum == 7)
              result = LOST;
                   else
              result = CONTINUE;
        }

        if( result == WIN)
            printf("The player win\n", result);
                if( result == LOST)
            printf("The player lost\n", result);
return 0;

}

int roll(void)
{
        int die1, die2;
        srand(time(NULL));
        die1 = rand() % 6 + 1;
        die2 = rand() % 6 + 1;
        printf("Player rolled %d + %d = %d\n", die1, die2, die1 + die2);
return die1 + die2;}

Good afternoon, everyone. I'm Kate.

and yet you post as "Jenny"...
I am curious about where to place
the sentence:
srand ( time ( NULL ) );

this is a statement not a sentence

In this program, if I  place it in function -------  int roll
( void ) ,

this is usually a bad idea

I always get a wrong result

But if I place the sentence in function ------- int main (), the
program executes successfully.
I don't quite understand .Can you help me ?

you should usually have only one call to srand() in your program.
rand() produces a sequence of (pseudo) random numbers. srand()
tells rand() where to "start" the sequence. The value passed to
srand() is referred to as the seed of the (pseudo) random
number generator. The PRG should only be seeded once.

Why "psudo" random number generator? Well PRNs are produced
by running a function. Such a function is actually
completly predicatable and if you don't know the seed
and the function used only appears to be random.


--
Nick Keighley

"Anyone attempting to generate random numbers by deterministic
means is, of course, living in a state of sin."
-- John Von Neumann

In a sense, there is no such thing as a random number;
for example, is 2 a random number?
(D.E.Knuth)
 
N

Nick Keighley

Ok, if you read man you should see some notes says that you shouldn't
use constructions like that:


Use

          die1 = 1.0 + (int) (6.0 * rand() / (RAND_MAX + 1.0));

or something like that (that uses high bits).

I assume you meant the comp.lang.c Frequently Asked Questions
("The FAQ"). If you are going to try and help newbies try
and give a good quality answer. Things like "if you read man..."
are just crap.

The FAQ may be found at http://c-faq.com/

Useful FAQs:

FAQ 13.16 "How can I get random integers in a certain range?"
explains why simply taking the modulaus is a bad idea

FAQ 13.17 "Each time I run my program, I get the same sequence
of numbers back from rand()"
discusses the correct usage of srand().

It is worth reading the rest of the FAQ. Both of you.
 
V

viza

Hi maverik

Ok, if you read man you should see some notes says that you shouldn't
use constructions like that:

Use
die1 = 1.0 + (int) (6.0 * rand() / (RAND_MAX + 1.0));

or something like that (that uses high bits).

I disagree.

If the C library is broken is not the job of every application to work
around it. (rand() % 6 + 1) is the correct way to get a non-secure but
reasonably random number between 1 and 6.

It is wrong that any rand(3) manual page or other documentation suggests
what you have just suggested. On systems where rand(3) doesn't work
well, the implementation should be fixed. An OS or distro that leaves it
unfixed long enough to make it worth documenting should be avoided. In
this case there can be no reason for trying to maintain backwards
compatibility to the worse version.

It is easy to read and quote the same old advice, but it applies to
almost no-one, and following convoluted workarounds as a matter of course
whether they are needed or not can lead to unreadable code and unexpected
bugs, so I advise to avoid it :).
 
V

viza

Hi maverik

Ok, if you read man you should see some notes says that you shouldn't
use constructions like that:

Use
die1 = 1.0 + (int) (6.0 * rand() / (RAND_MAX + 1.0));

or something like that (that uses high bits).

I disagree.

If the C library is broken is not the job of every application to work
around it. (rand() % 6 + 1) is the correct way to get a non-secure but
reasonably random number between 1 and 6.

It is wrong that any rand(3) manual page or other documentation suggests
what you have just suggested. On systems where rand(3) doesn't work
well, the implementation should be fixed. An OS or distro that leaves it
unfixed long enough to make it worth documenting should be avoided. In
this case there can be no reason for trying to maintain backwards
compatibility to the worse version.

It is easy to read and quote the same old advice, but it applies to
almost no-one, and following convoluted workarounds as a matter of course
whether they are needed or not can lead to unreadable code and unexpected
bugs, so I advise to avoid it :).
 
M

maverik

I assume you meant the comp.lang.c Frequently Asked Questions
("The FAQ").

No. From Linux man pages:

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).
If you are going to try and help newbies try
and give a good quality answer. Things like "if you read man..."
are just crap.

I said it to show that I read it in the manual. So, if Jenny want to
check my answer or read more (that is not mentioned in this post)
about rand() / srand() she can do it reading man page.
I didn't say: "RTFM, stupid girl".
The FAQ may be found athttp://c-faq.com/

Thanks, I know.
Useful FAQs:

FAQ 13.16 "How can I get random integers in a certain range?"
explains why simply taking the modulaus is a bad idea

FAQ 13.17 "Each time I run my program, I get the same sequence
of numbers back from rand()"
discusses the correct usage of srand().

It is worth reading the rest of the FAQ. Both of you.

Jenny, sorry if my post hurts you.
 
V

viza

Hi
Good afternoon, everyone. I'm Kate.I am curious about where to place the
sentence:
srand ( time ( NULL ) );
In this program, if I place it in function ------- int roll ( void )
,I always get a wrong result, such as: 4 + 1 = 5;
4 + 5 = 9; 4 + 1 = 5;
4 + 5 = 9 The player win.
The player win.
Press any key to continue. Press any key to
continue.
The player can win every time.

As Nick said, call srand() once, before you call rand() for the first
time (usually near the start of main). If you call srand(time(NULL))
twice in the same second, then your random numbers will probably not be
random at all.

I'm not sure I understand what you mean by wrong result. If you are
getting the dice coming up with the same numbers every time, this is
perhaps the problem. Otherwise you need to show us the actual output of
the program and what you think it should be.

HTH
viza
 
M

maverik

Hi maverik





I disagree.

If the C library is broken is not the job of every application to work
around it.  (rand() % 6 + 1) is the correct way to get a non-secure but
reasonably random number between 1 and 6.

I didn't said that (rand() % 6 + 1) is incorrect.
It is wrong that any rand(3) manual page or other documentation suggests
what you have just suggested.
It is easy to read and quote the same old advice, but it applies to
almost no-one, and following convoluted workarounds as a matter of course
whether they are needed or not can lead to unreadable code and unexpected
bugs, so I advise to avoid it :).

c-faq.com
Section 13.17

The obvious way,

rand() % N /* POOR */

(which tries to return numbers from 0 to N-1) is poor, because the low-
order bits of many random number generators are distressingly non-
random. (See question 13.18.) A better method is something like

(int)((double)rand() / ((double)RAND_MAX + 1) * N)

Thanks to Nick. Do you think it is old too? Or may be wrong? I can
make mistakes as every of us. And if you show me the right answer
(link to the document, book, etc) (with proof) I will say thanks.
 
N

Nick Keighley

I assume you meant the comp.lang.c Frequently Asked Questions
("The FAQ").

No. From Linux man pages:

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:

how do you know Jenny is using linux? How do you know she knows
what "read man" means?

"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).

yes but you didn't quote that

I said it to show that I read it in the manual.

"that I read it on the linux man page"
So, if Jenny want to
check my answer or read more (that is not mentioned in this post)
about rand() / srand() she can do it reading man page.
I didn't say: "RTFM, stupid girl".


Thanks, I know.

so why not refer to it?


<snip>
 
M

maverik

"that I read it on the linux man page"

1. Thanks. I trying to improve my english as much as I can. Of course,
it is not ideal because it isn't my native language.

2. You choose wrong place to check my english I think. If you want
just show that you know more than I in any field of knowledge I would
not argue with you.
 
J

Jenny

I consider that "time(NULL)" stands for the time when the program
executes. In my opinion each time the rand() should get different
result.But actually it stays the same while I place the sentence( srand
(time(NULL)) )among the module
 
J

Jenny

I consider that "time(NULL)" stands for the time when the program
executes. In my opinion each time the rand() should get different
result.For example,
5+4=9
2+6=8
3+4=7
The player lost.
But actually it stays the same while I place the sentence( srand(time
(NULL)) )among the module. I cannot understand.
 
N

Nick Keighley

1. Thanks. I trying to improve my english as much as I can. Of course,
it is not ideal because it isn't my native language.

2. You choose wrong place to check my english I think. If you want
just show that you know more than I in any field of knowledge I would
not argue with you.

I wasn't taking issue with your english but with the fact that you
assume a random person knows what "read man" means. Most Windows
users wouldn't have a clue what that meant.

You can have the last word if you want
 
N

Nick Keighley

I consider that "time(NULL)" stands for the time when the program
executes. In my opinion each time the rand() should get different
result.For example,
5+4=9
2+6=8
3+4=7
The player lost.
But actually it stays the same while I place the sentence( srand(time
(NULL))  )among the module. I cannot understand.

a program like you's will run very quickly.

It is simply using the same time over and over again.

Try printing the value of time(NULL) in your roll()
function. You may be enlightened.


Have you read the FAQs I suggested?
 
M

maverik

I wasn't taking issue with your english but with the fact that you
assume a random person knows what "read man" means. Most Windows
users wouldn't have a clue what that meant.

Yes, I miss it. You are right. I don't want to have last word, I'm not
trolling, not arguing. If I'm mistaken, then I say about it. Yes, I
agree with you, that it was my fail with linux man pages, because I
didn't get the fact that random person can use Windows.

I am not an enemy to you and don't wanna be. Please, sorry if I hurt
you.
 
J

James Kuyper

Jenny wrote:
....
I consider that "time(NULL)" stands for the time when the program
executes. In my opinion each time the rand() should get different
result.

The standard doesn't specify what type time_t is, nor how it represents
the time. However, it's not uncommon for it to have a resolution of 1
second. How many operations can your computer perform in one second?
 
N

Nate Eldredge

viza said:
Hi maverik



I disagree.

If the C library is broken is not the job of every application to work
around it. (rand() % 6 + 1) is the correct way to get a non-secure but
reasonably random number between 1 and 6.

Well, if RAND_MAX+1 is not a multiple of 6, there is some bias in this
approach even if rand() returns a perfectly random number with precisely
uniform distribution. This would be more noticeable if you had a limit
bigger than 6. (If your limit was bigger than RAND_MAX / 2, you would
see some values coming up twice as often as others.)

Better would be

int rand_less_than_n(int n) {
int r;
while ((r = rand()) < ((RAND_MAX % n) + 1) % n) ;
return r % n;
}

The double-mod is to handle the (common) case where RAND_MAX == INT_MAX,
so that RAND_MAX+1 would overflow an int.

Many languages provide a function with this effect as the main interface
to the PRNG. I've always been a bit annoyed that C doesn't, since, as
we see, people often don't get it right when doing it themselves.
Languages that give you a floating-point value uniformly distributed in
(some discrete subset of) [0,1) suffer from the same issue as C, only
more subtly since it's harder to work out how many possible values can
be returned (probably the number of possible mantissa values).
It is wrong that any rand(3) manual page or other documentation suggests
what you have just suggested. On systems where rand(3) doesn't work
well, the implementation should be fixed. An OS or distro that leaves it
unfixed long enough to make it worth documenting should be avoided. In
this case there can be no reason for trying to maintain backwards
compatibility to the worse version.

I agree with this.
 
K

Keith Thompson

viza said:
Hi maverik



I disagree.

If the C library is broken is not the job of every application to work
around it. (rand() % 6 + 1) is the correct way to get a non-secure but
reasonably random number between 1 and 6.

It is wrong that any rand(3) manual page or other documentation suggests
what you have just suggested. On systems where rand(3) doesn't work
well, the implementation should be fixed. An OS or distro that leaves it
unfixed long enough to make it worth documenting should be avoided. In
this case there can be no reason for trying to maintain backwards
compatibility to the worse version.

It is easy to read and quote the same old advice, but it applies to
almost no-one, and following convoluted workarounds as a matter of course
whether they are needed or not can lead to unreadable code and unexpected
bugs, so I advise to avoid it :).

The trouble is, many real-world C implementations *do* have poor
rand() functions, perhaps partly because the C standard provides a
sample implementation. Certainly a rand() implementation should be as
good as possible, but I'm not going to reject an implementation just
because its rand() is poor. Many implementations provide alternate
PRNGs, typically ones that don't fit into the standard's requirements
for rand() and srand().

Disclaimer: I don't actually know what the current state of rand()
implementations is. If I'm wrong, if most or all existing
implementations have been enhanced so the low-order bits are as good
as the high-order bits, then my argument is weakened. Does anyone
know the actual current state of the art? Do any existing
implementations still use the sample implementation given in the C
standard?
 

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

No members online now.

Forum statistics

Threads
473,999
Messages
2,570,246
Members
46,841
Latest member
WilmerBelg

Latest Threads

Top