For Programmers: Free Programming Magazines  


Home > Archive > Unix Programming > September 2006 > Generate Random number









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Generate Random number
axsmth@gmail.com

2006-09-16, 7:01 pm

Hi,
I am using the following approach to generate a random number

//To generate values from 0 to max
int randomGen(int max)
{
srand((unsigned int)time(NULL));
return rand()%max;
}

However when using this function for max = 2 across processes, I am
getting a series
of 0s for each process.
Is there a workaround or a better way to seed ?
Thanks,
Max

Paul Pluzhnikov

2006-09-16, 7:01 pm

axsmth@gmail.com writes:

> //To generate values from 0 to max
> int randomGen(int max)
> {
> srand((unsigned int)time(NULL));
> return rand()%max;
> }


This isn't how you are supposed to use rand().
You should seed it *once*, and then just use rand() result.

I've reproduced the behaviour you observed (all 0s) on Linux Fedora
Core 2, and also verified that you don't get a string of 0s if you
don't re-seed on every iteration.

There might be a good explanation why re-seeding rand() before each
call always produces an even number on the subsequent rand() call,
but I don't understand glibc source well enough to explain that.

Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
axsmth@gmail.com

2006-09-16, 7:01 pm


Hi,
As you suggested, I removed the srand call from the function so that
the call is made only once. However, Now only 1s are generated. Is
there some default behavior?
Thanks

toby

2006-09-16, 7:01 pm

axsmth@gmail.com wrote:
> Hi,
> As you suggested, I removed the srand call from the function so that
> the call is made only once. However, Now only 1s are generated. Is
> there some default behavior?


Some implementations have poor quality low bits. Try taking a higher
order bit (e.g. (rand()>>15)&1 ) or use a different RNG - some
suggestions here
http://groups.google.com/group/comp...e72f0552?hl=en&

> Thanks


Paul Pluzhnikov

2006-09-16, 10:01 pm

axsmth@gmail.com writes:

> As you suggested, I removed the srand call from the function so that
> the call is made only once. However, Now only 1s are generated.


Any implementation on which successful calls to rand() produce only
odd numbers is severely broken.

I seriously doubt that your implementation is so broken; more likely
you have a bug in your test program. Can we see your test program,
and what platform are you on?

Cheers,

P.S. Here is my test:

#include <stdio.h>
int randomGen(int max) { return rand()%max; }
int main()
{
int i;
srand((unsigned int)time(NULL));
for (i = 0; i < 100; ++i) printf("%d ", randomGen(2));
printf("\n");
return 0;
}

And output on Fedora Core 2:
0 1 0 0 0 0 1 1 1 1 0 1 0 0 1 0 0 1 1 0 1 0 1 0 1 0 1 1 0 0 0 0 1 0 1 1 1 0 0 0 1 0 1 1 0 1 0 0 0 1 1 1 1 0 1 1 0 1 0 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 1 1 1 1 0 1 0 1 0 1 1 0 0 0 1 0 0 0 1 1 0 0 1 0 0 1

--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
axsmth@gmail.com

2006-09-17, 4:00 am


Hi,
Ya I aslo created a small program to test the function which does
return 0s and 1s.
However when I use it in my actual program, it gives the problem.
The actual program has a many processes which have to take a routing
decision using the random generator. And they call the function
multiple time.
Thanks,
Max

Paul Pluzhnikov

2006-09-17, 4:00 am

axsmth@gmail.com writes:

> Ya I aslo created a small program to test the function which does
> return 0s and 1s.
> However when I use it in my actual program, it gives the problem.


Perhaps your actual program repeats the mistake you made originally:
calls srandom() repeatedly (from somewhere else in the code)?

> The actual program has a many processes which have to take a routing
> decision using the random generator.


The processes are all independent; so the fact that there are many
of them is irrelevant; each one will generate random sequence of
its own.

If they all are fork()ed after the initial call to srandom(),
they'll each get *the same* "random" sequence, which may or may
not be what you want.

Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
Wayne C. Morris

2006-09-17, 7:00 pm

In article <1158471650.085708.89070@e3g2000cwe.googlegroups.com>,
axsmth@gmail.com wrote:

> Hi,
> Ya I aslo created a small program to test the function which does
> return 0s and 1s.
> However when I use it in my actual program, it gives the problem.
> The actual program has a many processes which have to take a routing
> decision using the random generator. And they call the function
> multiple time.


If two processes call srand() with the same seed value, they'll get the
same sequence of random numbers.

So each new process must call srand() after the fork(), passing different
seed values to srand().

time() won't give a good seed value if there's any chance that two or more
processes will be started within the same one-second period, because
they'll get the same time() value for their seed.

gettimeofday() would be a little better, if you combine the tv_sec and
tv_usec values, but you'd still get duplicate seeds if two processes start
within 1 millisecond of each other.

I'd try combining the process ID with tv_sec and tv_usec, using a simple
hash function.
toby

2006-09-17, 7:00 pm

Wayne C. Morris wrote:
> In article <1158471650.085708.89070@e3g2000cwe.googlegroups.com>,
> axsmth@gmail.com wrote:
>
>
> If two processes call srand() with the same seed value, they'll get the
> same sequence of random numbers.
>
> So each new process must call srand() after the fork(), passing different
> seed values to srand().
>
> time() won't give a good seed value if there's any chance that two or more
> processes will be started within the same one-second period, because
> they'll get the same time() value for their seed.
>
> gettimeofday() would be a little better, if you combine the tv_sec and
> tv_usec values, but you'd still get duplicate seeds if two processes start
> within 1 millisecond of each other.
>
> I'd try combining the process ID with tv_sec and tv_usec, using a simple
> hash function.


You can also seed from the kernel RNG /dev/urandom (or if you don't
mind waiting for entropy, /dev/random). This is particularly handy if
the seeds are longer than 32 bits (e.g. Marsaglia's generators).

axsmth@gmail.com

2006-09-19, 10:01 pm


>
> You can also seed from the kernel RNG /dev/urandom (or if you don't
> mind waiting for entropy, /dev/random). This is particularly handy if
> the seeds are longer than 32 bits (e.g. Marsaglia's generators).


How to do that in code?
Thanks

toby

2006-09-19, 10:01 pm

axsmth@gmail.com wrote:
>
> How to do that in code?


$ cat seed.c
#include <stdio.h>
int main(){
unsigned long seed;
FILE *rng = fopen("/dev/urandom","r");

// whenever you need a new seed or 32-bit random number:
fread(&seed, sizeof(seed), 1, rng);
printf("%#x\n", seed);

fclose(rng);
return 0;
}
$ ./seed
0xae78550b

> Thanks


Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com