サイコロ #6

擬似乱数の生成にdSFMT ver.2.2を使用して実験してみる。
せっかくなのでSSE2を使用するコードを生成させ、
周期はたぶんデフォルトのDSFMT_MEXP=19937を指定する。
まず、#1のルールにしたがって、一億回ダイスを振ってみる。

dice1.c
#include <stdio.h>
#include "dSFMT.h"

int main(void) {
    const int seed = 13579;
    const unsigned int N = 100000000;
    dsfmt_t dsfmt;
    unsigned int i, x, c[6], s;
    double e;

    for (i = 0; i < sizeof(c) / sizeof(c[0]); i++) c[i] = 0;
    dsfmt_init_gen_rand(&dsfmt, seed);
    for (i = 0; i < N; i++) {
        x = dsfmt_genrand_close_open(&dsfmt) * 6;
        c[x]++;
    }
    s = 0;
    for (i = 0; i < sizeof(c) / sizeof(c[0]); i++) {
        printf("%u ", c[i]);
        s += c[i];
    }
    printf("%u\n", s);
    e = 0;
    for (i = 0; i < sizeof(c) / sizeof(c[0]); i++) e += (double)c[i] / s * i;
    printf("%f\n", e);
    return 0;
}

dSFMTのソースコード自体はC99としてコンパイルする必要があるが、
そのヘッダファイルdSFMT.hはC89のソースの一部としてインクルードできた。
各得点の回数はunsigned intでカウントしているが、
試行回数のN(=100000000)もunsigned intなのでオーバーフローの心配はないはず。
実行する。

$ ./dice1
16667460 16671961 16667210 16666741 16664688 16661940 100000000
2.499751

一行目は0から5までそれぞれ得点した回数とその総計(=1億)、
二行目は得点の平均値である。
#1で示した通り、得点0から5までのそれぞれが約1/6で発生しており、
一億回分の得点の平均値は約2.5になっている。