Python Random vs. Cython C Rand for Dice Rolls

Chris Angelico rosuav at gmail.com
Sun Jun 7 13:33:00 EDT 2015


On Mon, Jun 8, 2015 at 3:17 AM, C.D. Reimer <chris at cdreimer.com> wrote:
> The Python random shows a uniform bell curve with low numbers at the ends
> and the peak in the middle, which is similar to the text in the book for the
> BASIC program. The Cython C rand is over all the place (especially with a
> negative number), which reminds me how bad the random number generator was
> on my 1MHz C64 in the day.

The negative result is a strong indicator that you're not seeing the
results of rand() here. While there is a potential for bias (check out
RAND_MAX, and consider that there may be some small bias there;
although on most modern systems, RAND_MAX is going to be high enough
that the bias from modulo 6 won't be highly visible), it's much MUCH
more likely that you're looking at uninitialized memory. I'm not
overly familiar with Cython, but can you simply add "={0}" to the
declaration to force it to be initialized to all zeroes? That's what
I'd do in raw C. Here's the same thing done in straight-forward C:

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

void roll(int *f,int x)
{
    int i, a, b;
    for (i=0; i<x; ++i)
    {
        a = rand() % 6 + 1;
        b = rand() % 6 + 1;
        f[(a + b) - 1] += 1;
    }
}

int main()
{
    int f[12];
    int i;
    roll(f, 50000000);
    for (i=1;i<12;++i)
        printf("%-15d %d\n", i+1, f[i]);
    return 0;
}

rosuav at sikorsky:~$ time ./a.out
2               1387782
3               6972536
4               4170215
5               21326281
6               6945600
7               8334121
8               6943983
9               9750611
10              4168554
11              6972254
12              1389371

real 0m1.089s
user 0m1.088s
sys 0m0.000s

Similar weird results to yours. Replacing "int f[12];" with "int
f[12]={0};" produces a much more plausible bell curve:

rosuav at sikorsky:~$ time ./a.out
2               1387782
3               2776523
4               4170215
5               5552330
6               6945600
7               8334121
8               6943983
9               5554675
10              4168554
11              2776846
12              1389371

real 0m1.093s
user 0m1.088s
sys 0m0.000s

But I don't know Cython, so I don't know whether this would work as-is
or not. Worst case, toss in a quick initialize-to-zero loop above your
main loop, and you can at least verify correctness.

ChrisA



More information about the Python-list mailing list