I am trying to better understand the behavior of a loop containing some sort of a rand() as its end condition. Consider the following example:

``for(int i=0; i < rand()%6+10; i++) { do something }``

In this case, the loop will iterate between 10 to 15 times.

My question is: Will the termination value be evaluated once and then reused for the rest of the iterations? or will it be re-evaluated with each iteration?

In addition, is this considered bad practice?

The condition is evaluated fully before each iteration. (Think about it: how would the compiler know which parts you want evaluated each time, and which parts you don't?)

Whether or not it is bad practice depends on the situation. In cases where the termination condition may change during the loop, it makes sense. If you want to loop a random number of times then you should pre-evaluate the termination value, or you will wind up with a different random distribution than you think you have.

If you evaluate `rand()` on each iteration then the odds of the termination condition being met would change each iteration depending on the value of `i`, and you would find some terminating values of `i` over-represented compared to a uniform distribution. Having said that, in your case the distribution wouldn't be uniform anyway, even if you evaluated it ahead of time, because (1) `rand()` is not guaranteed to produce values with uniform distribution to my knowledge, and (2) taking the modulus of a random function where the range is not evenly divisible by the modulus will skew the distribution. The larger the range of the random function the less the skew will be given a particular modulus, but it will still be present.

The C++ standard says that the `for` statement:

`for ( for-init-statement conditionopt ; expressionopt ) statement`

is equivalent to:

```{ for-init-statement while ( condition) { statement expression ; } }```

[ Note: Thus the first statement specifies initialization for the loop; the condition (6.4) specifies a test, made before each iteration, [...]

So yes, the condition will be re-evaluated with each iteration.

As for whether or not using `rand()` is bad practice... the `rand()` function is library and platform dependent. On linux, you can find documentation by doing `man 3 rand`. For example, the online man page says:

Do not use this function in applications intended to be portable when good randomness is needed.

And cppreference's opinion on std::rand:

There are no guarantees as to the quality of the random sequence produced. In the past, some implementations of `rand()` have had serious shortcomings in the randomness, distribution and period of the sequence produced (in one well-known example, the low-order bit simply alternated between 1 and 0 between calls).

rand() is not recommended for serious random-number generation needs, like cryptography. It is recommended to use C++11's random number generation facilities to replace `rand()`. (since C++11)

If you want a solid introduction on how to use these C++11 features, consult Random number generation in C++11, how to generate, how do they work?.

For an analysis on various usages of `rand()` and why they're bad, see Julienne Walker's article.

For example:

``````1 int r = rand() % N;
``````

To instead add a lower bound and set the range to [M..N), one might do this:

``````1 int r = M + rand() % ( N - M );
``````

Anyone who does this will be rewarded with a seemingly random sequence and be thrilled that their clever solution worked. Unfotunately, this does not work. The first solution only works when N evenly divides into RAND_MAX. The second solution isn't any better. The reason is because forcing the range in this way eliminates any chance of having a uniform distribution. Now, this is okay if you care nothing about some numbers being more probable than others, but to be correct, you must work with the distribution instead of destroy it.

Top