Why is (rand() % anything) always 0 in C++?
I am having trouble getting rand()
to work in C++. rand()
normally gives me a very large number. When I try to use the modulo operator (%
) to give it a ra开发者_运维问答nge, it always returns 0, no matter what.
Seeding the random number generator at the beginning of the program doesn't help either.
I think this is common if the random generator algorithm leaves a certain pattern of bits as zero. (For example, if the low-order bits are zero, the number mod some low constant will always be zero.)
Maybe you should try something like:
const int desired_maximum = /* ... */;
int r = (((double)rand()) / RAND_MAX) * desired_maximum;
For example in this manpage link, it says:
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
and never by anything resemblingj = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));(which uses lower-order bits)."j = 1 + (rand() % 10);
The following code works just fine for me (emitting a random number between 0 included and 1000 excluded each time it's run):
#include <cstdlib>
#include <ctime>
#include <iostream>
int main()
{
std::srand(time(0));
std::cout<<(std::rand() % 1000)<<std::endl;
return 0;
}
It appears that your immediate problem has been dealt with, but I think it's still worth mentioning one more point. Using the remainder to clamp outputs from rand to a specified range will usually cause bias in the results. To be specific, if the range of the generator (RAND_MAX in the case of C or C++) isn't a multiple of the range you're clamping to, some outputs will occur more often than others. For comparison, consider trying to divide 11 candies evenly between 3 children (without breaking any into pieces). The only way you can do it is NOT hand out some of the candy. Likewise, with a random number generator, the only way to get an even distribution in your output is not use some of the inputs.
int rand_lim(int limit) {
/* return a random number between 0 and limit inclusive.
*/
int divisor = RAND_MAX/(limit+1);
int retval;
do {
retval = rand() / divisor;
} while (retval > limit);
return retval;
}
As asveikau pointed out in his post, you generally want to use the upper bits from a typical linear congruential generator. The lower bits are generally more predictable. By dividing instead of taking a remainder, this retains upper bits. Though this does have a while loop, it often executes only once, and rarely more than twice, so its impact on performance is pretty minimal.
Whether this is worthwhile depends on the use you're making of the numbers you generate -- if you want dice or cards for a game that your kids will play a couple of times, using a remainder generally won't hurt a thing. If you're trying to do some sort of Monte Carlo simulation (for example) you probably want to be a bit more careful though...
精彩评论