Originally Posted by
iMalc
The problem is that here N is 6 which does not divide evenly into RAND_MAX. Whilst that method is good enough for most purposes, it is not statistically unbiased. A correct way to do it is to replace the rand() % N with the rejection method.
Now I understand what you guys are talking about.
rand() % 6 produces 1 too many 0 and 1 outcomes, with the totals being:
0 : 5462
1 : 5462
2 : 5461
3 : 5461
4 : 5461
5 : 5461
total = 32768
your method restores equality:
0 : 5461
1 : 5461
2 : 5461
3 : 5461
4 : 5461
5 : 5461
total = 32766
Thanks for that insight. I would of never have figured that out. I never gave any thought to RAND_MAX and took it
for granted that scaling rand() with % n just worked and did its magic.
Although this accounted for some of the error, I am still getting incorrect figures. I was, however, able to get
correct figures coding the dice rolling function differently. Consider the following two functions:
Code:
int roll_dice(void)
{
int die1, die2;
do {
die1 = rand();
} while (die1 >= (RAND_MAX / 6) * 6);
die1 = die1 % 6 + 1;
do {
die2 = rand();
} while (die2 >= (RAND_MAX / 6) * 6);
die2 = die2 % 6 + 1;
return die1 + die2;
}
Code:
int roll_dice2(void)
{
/* This produces more accurate dice sum distribution: */
int dice, sum[36] = { 2,3,3,4,4,4,5,5,5,5,6,6,6,6,6,7,7,7,7,7,7,
8,8,8,8,8,9,9,9,9,10,10,10,11,11,12 };
do {
dice = rand();
} while (dice >= (RAND_MAX / 36) * 36);
return sum[dice % 36];
}
They both do the same thing - return the sum of two random dice, but with different methods. The first function randomizes two separate die values and returns their sum, the second function randomizes a summation selection (randomly picks 1 valid sum from all possible sum values initialized in an array). The sum values are also repeated in correct amounts to model the probability occurrences correctly.
For some reason, the second function models the probability distribution for the sum of two dice better. It consistently outperforms the first function with 1 billion calls.