How to generate either 0 or 1 randomly in C

2019-09-20 10:32发布

问题:

I have read so many posts on this topic:

How does rand() work? Does it have certain tendencies? Is there something better to use?

How does the random number generator work in C

and this is what I got:

1) xn+1 depends on xn i.e., previous random number that is generated.

2) It is not recommended to initialize the seed more than once in the program.

3) It is a bad practice to use rand()%2 to generate either 0 or 1 randomly.

My questions are:

1) Are there any other libraries that I missed to take a look to generate a completely random number (either 0 or 1) without depending on previous output?

2) If there is any other work around using the inbuilt rand() function to satisfy the requirement?

3) What is the side effect of initializing the seed more than once in a program?

Code snippet:

srand(time(NULL));
d1=rand()%2;
d2=rand()%2;

Here my intention is to make d1 and d2 completely independent of each other.

My initial thought is to do this:

srand(time(NULL));
d1=rand()%2;
srand(time(NULL));
d2=rand()%2;

But as I mentioned earlier which is based on other posts, this is a bad practice I suppose?

So, can anyone please answer the above questions? I apologize if I completely missed an obvious thing.

回答1:

  1. Are there any other libraries that I missed to take a look to generate a completely random number between 0 and 1 without depending on previous output?

Not in the standard C library. There are lots of other libraries which generate "better" pseudo-random numbers.

  1. If there is any other work around using the inbuilt rand() function to satisfy the requirement?

Most standard library implementations of rand produce sequences of random numbers where the low-order bit(s) have a short sequence and/or are not as independent of each other as one would like. The high-order bits are generally better distributed. So a better way of using the standard library rand function to generate a random single bit (0 or 1) is:

(rand() > RAND_MAX / 2)

or use an interior bit:

(rand() & 0x400U != 0)

Those will produce reasonably uncorrelated sequences with most standard library rand implementations, and impose no more computational overhead than checking the low-order bit. If that's not good enough for you, you'll probably want to research other pseudo-random number generators.

All of these (including rand() % 2) assume that RAND_MAX is odd, which is almost always the case. (If RAND_MAX were even, there would be an odd number of possible values and any way of dividing an odd number of possible values into two camps must be slightly biased.)

  1. What is the side effect of initializing the seed more than once in a program?

You should think of the random number generator as producing "not very random" numbers after being seeded, with the quality improving as you successively generate new random numbers. And remember that if you seed the random number generator using some seed, you will get exactly the same sequence as you will the next time you seed the generator with the same seed. (Since time() returns a number of seconds, two successive calls in quick succession will usually produce exactly the same number, or very occasionally two consecutive numbers. But definitely not two random uncorrelated numbers.)

So the side effect of reseeding is that you get less random numbers, and possibly exactly the same ones as you got the last time you reseeded.



回答2:

1) Are there any other libraries that I missed to take a look to generate a completely random number between 0 and 1 without depending on previous output?

This sub-question is off-topic for Stack Overflow, but I'll point out that POSIX and BSD systems have an alternative random number generator function named random() that you could consider if you are programming for such a platform (e.g. Linux, OS X).

2) If there is any other work around using the inbuilt rand() function to satisfy the requirement?

Traditional computers (as opposed to quantum computers) are deterministic machines. They cannot do true randomness. Every completely programmatic "random number generator" is in practice a psuedo-random number generator. They generate completely deterministic sequences, but the values from a given set of calls are distributed across the generator's range in a manner approximately consistent with a target probability distribution (ordinarily the uniform distribution).

Some operating systems provide support for generating numbers that depend on something more chaotic and less predictable than a computed sequence. For instance, they may collect information from mouse movements, CPU temperature variations, or other such sources, to produce more objectively random (yet still deterministic) numbers. Linux, for example, has such a driver that is often exposed as the special file /dev/random. The problem with these is that they have a limited store of entropy, and therefore cannot provide numbers at a sustained high rate. If you need only a few random numbers, however, then that might be a suitable source.

3) What is the side effect of initializing the seed more than once in a program?

Code snippet:

srand(time(NULL));
d1=rand()%2;
d2=rand()%2;

Here my intention is to make d1 and d2 completely independent of each other.

My initial thought is to do this:

srand(time(NULL));
d1=rand()%2;
srand(time(NULL));
d2=rand()%2;

But as I mentioned earlier which is based on other posts, this is a bad practice I suppose?

It is indeed bad if you want d1 and d2 to have a 50% probability of being different. time() returns the number of seconds since the epoch, so it is highly likely that it will return the same value when called twice so close together. The sequence of pseudorandom numbers is completely determined by the seed (this is a feature, not a bug), and when you seed the PRNG, you restart the sequence. Even if you used a higher-resolution clock to make the seeds more likely to differ, you don't escape correlation this way; you just change the function generating numbers for you. And the result does not have the same guarantees for output distribution.

Additionally, when you do rand() % 2 you use only one bit of the approximately log2(RAND_MAX) + 1 bits that it produced for you. Over the whole period of the PRNG, you can expect that bit to take each value the same number of times, but over narrow ranges you may sometimes see some correlation.

In the end, your requirement for your two random numbers to be completely independent of one another is probably way overkill. It is generally sufficient for the pseudo-random result of one call to be have no apparent correlation with the results of previous calls. You probably achieve that well enough with your first code snippet, even despite the use of only one bit per call. If you prefer to use more of the bits, though, then with some care you could base the numbers you choose on the parity of the count of how many bits are set in the values returned by rand().



回答3:

Use this

(double)rand() / (double)RAND_MAX

completely random number ..... without depending on previous output?

Well in reality computers can't generate completely random numbers. There has to be some dependencies. But for almost all practical purposes, you can use rand().

side effect of initializing the seed more than once

No side effect. But that would mean you're completely invalidating the point of using rand(). If you're re initilizeing seed every time, the random number is more dependent on time(and processor).

any other work around using the inbuilt rand() function

You can write something like this:

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

int main(int argc,char *argv[])
{
    srand(time(NULL));
    printf("%lf\n",(double)rand()/(double)RAND_MAX);
    printf("%lf\n",(double)rand()/(double)RAND_MAX);
}

If you want to generate either a 0 or a 1, I think using rand()%2 is perfectly fine as the probability of an even number is same as probability of an odd number(probability of all numbers is equal for an unbiased random number generator).



标签: c random