0

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.

Community
  • 1
  • 1
  • 1
    Way too broad and way too many questions! Do you know the difference between random-numbers and numbers obtained from pseudo-random number generators? (Hint: with a PRNG: every number ```x_i``` is completely dependent on the previous ones. This changes when reseeding with some entropy-source like time; but this is highly complex and most people do not understand the consequences) – sascha Oct 03 '16 at 19:58
  • 2
    Possible duplicate of [How to generate a random number in C?](http://stackoverflow.com/questions/822323/how-to-generate-a-random-number-in-c) – mazhar islam Oct 03 '16 at 20:02
  • The short answer is to call `srand(time(NULL))` exactly once at the beginning of your program, and then use `rand() / N` to generate your numbers. We choose N = ceil((`RAND_MAX` + 1) / 2), but in order to avoid overflow when `RAND_MAX == INT_MAX`, we compute it with the code `int N = RAND_MAX / 2 + 1`. – Dietrich Epp Oct 03 '16 at 21:43
  • @Dietrich Epp Your comments looks interesting, but see no advantage of `rand() / N` vs. `rand() % 2`. Could even use `rand() & 1` to avoid `div/mod` code. – chux - Reinstate Monica Oct 03 '16 at 22:30
  • @chux: `rand() % 2` doesn't emit any div or mod instructions when compiled. However, the reason why `rand() & 1` is a bad idea is because many random number generators have poor output in the lower bits. Linear congruential generators are still not uncommon, and in the words of Wikipedia, "The low-order bits of LCGs when m is a power of 2 should never be relied on for any degree of randomness whatsoever." – Dietrich Epp Oct 04 '16 at 00:44
  • @DietrichEpp "rand() % 2 doesn't emit any div or mod instructions when compiled" could happen is the compiler takes advantage of knowing `rand()` does not emit a negative answer, A common compiler would need to do `int % 2` in such a way to provide for 3 answers -1,0,1. Concerning quality of lower order bits: `rand() % 2` performs as well as `rand() & 1`. Interesting wiki point. – chux - Reinstate Monica Oct 04 '16 at 01:37
  • @chux: Whether `rand() % 2` emits div or mod instructions has nothing to do with the compiler knowing that `rand()` is always positive. Try it out yourself. I'm not sure why you're saying that `rand() % 2` has the same quality as `rand() & 1`... haven't we established that they produce identical results? – Dietrich Epp Oct 04 '16 at 02:10
  • @DietrichEpp If the compiler cannot assume `int rand(void)` returns non-negative values, then `int % 2` cannot assume to produce identical results to `int & 1`. When the `int` is negative, they generate different results and so need different code, possible a div/rem code with `int % 2`. – chux - Reinstate Monica Oct 04 '16 at 02:18
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/124840/discussion-between-dietrich-epp-and-chux). – Dietrich Epp Oct 04 '16 at 02:24

3 Answers3

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?

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.

rici
  • 234,347
  • 28
  • 237
  • 341
  • Why "should think of the random number generator as producing "not very random" numbers after being seeded" If this a concern of some random number generators? Certainly this is not specified behavior given that `rand()` is so weakly defined. – chux - Reinstate Monica Oct 03 '16 at 22:34
  • @chux I think this comes from the ```seeding from time```-idea. When reseeding, depending on the time, different seeds based on this time are not that different. And for some PRNGs (e.g. Mersenne Twister) it is known, that similar seeds take a long time to diverge / other perspective: it's hard to seed multiple MTs, so that there is no correlation between these outputs. – sascha Oct 03 '16 at 22:51
  • @chux: basically what sascha said. Most RNGs diverge slowly from similar seeds. Of course you could seed from a random number but chicken-and-egg :-). Of course it is not specified; neither is non-independence of low-order bits. But avoiding reseeding and not using low-order bits are both good advice IMHO. – rici Oct 03 '16 at 23:23
  • Agree with above except "Most RNGs diverge slowly from similar seeds". I am familiar with that weakness of MT, but do know of evidence that applies to _most_ PRNGs. – chux - Reinstate Monica Oct 04 '16 at 01:31
  • @chux, ok, *most* prngs is an overstatement. But its true of LCGs, which are still commonly used, and of MT. Anyway, all I'm suggesting is a defensive heuristic, not an absolute rule. – rici Oct 04 '16 at 08:48
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?

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

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Maybe `log2(RAND_MAX + 1.0)` instead of `log2(RAND_MAX) + 1` to compute a nice whole number answer? – chux - Reinstate Monica Oct 03 '16 at 21:11
  • @chux, I chose the formula I did because it does not presuppose that `RAND_MAX` is one less than a power of two, but I did silently suppose that the result would be truncated to an integer. And you will recognize that there are still a few values where it is off by one. Rather than go into all the details in the answer, I have updated it to remark that the bit count approximate. – John Bollinger Oct 04 '16 at 14:45
0

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

Raman
  • 2,735
  • 1
  • 26
  • 46
  • Detail: This will generate 0.0 and 1.0 from time-to-time. OP's goal is unclear concerning end-points. The `/ (double)RAND_MAX`, being inexact, also create small artifacts - yet this likely meets OP's goal. – chux - Reinstate Monica Oct 03 '16 at 20:09
  • Though the OP says *between* zero and one, his code says that he wants each number generated to be *either* zero or one. – John Bollinger Oct 03 '16 at 20:18
  • @JohnBollinger ok. added answer for *either a zero or a one* – Raman Oct 03 '16 at 20:29