期待値の確率とかけ離れている


C言語でサイコロを2個振ってゾロ目になる確率を求めるプログラムを書いているのですが, 実行結果が期待値のである1/36に近くならないです.  
以下, ソースです.

[code]

    #include <stdlib.h>
    #include <time.h>
    #include <sys/time.h>
    #include <unistd.h>
    
    int main(void){
        int i = 0;
        int microsecond = 1.0 * 1000;
        double count;
        int A,B,C,D,E,F;
        double sum;
        double average, avepro;
        sum = 0;
        struct timeval tv;
        gettimeofday(&tv, NULL);
        //srand((unsigned int)tv.tv_sec * ((unsigned int)tv.tv_usec + 1));
    
        srand(time(NULL)/60);
        
        //srand(tv.tv_sec + tv.tv_usec);
        
    
        for(count = 1;count < 101;count++){
        while (1){
        A = rand() % 6 + 1;
        usleep(microsecond);
        B = rand() % 6 + 1;
        C = rand() % 6 + 1;
        D = rand() % 6 + 1;
        E = rand() % 6 + 1;
        F = rand() % 6 + 1;
        i++;
        printf("A:%d,B:%d\n", A, B);
        //printf("A:%d:B:%d:C:%d:D:%d:E:%d:F:%d\n", A, B, C, D, E, F);
        if(A == B)
        //if(A == B && B == C && C == D && D == F)
        break;
        }
        sum += i;
        printf("%dで一致しました:試行回数は%d回です.\n", A,i);
        i = 0;
        }
        average = sum / (count + 1);
        avepro = average / 100;
        printf("平均回数:%f\n", average);
        printf("平均確率:%f\n", avepro);
        return 0;
    }
    
[/code]




Чайкаさんが指摘されている通り、期待値は 6/36 ですね。

そのほか指摘されていない点として

>
[code]

>     usleep(microsecond);
>  
[/code]

ウェイトを入れたところで乱数の結果は変化しません。時間の無駄となります。

>
[code]

>     double sum;
>     double average, avepro;
>     ...
>     sum += count;
>     ...
>     average = sum / (count + 1);
>  
[/code]

大きな数を扱うために`double`を選択したのでしょうか？
`double`は浮動小数点数であり大きな数を扱うことができると誤解されますが、`double`は仮数部つまり有効精度が52bitしかありません。有効精度以下の演算は丸め込まれるため、大きな数になった場合に
`sum += count` の演算は結果が変化しなくなります。結局、
**`double`は整数演算目的では52bit程度しか使えない**ことを覚えておくとよいでしょう。  
`uint64_t`もしくは`unsigned long long`の方がより大きな数を扱えます。`uint64_t`であれば64bitの整数を扱えます。

今回は関係ないようですが、[`rand()`は性能が悪く意図しない結果を引き起こすことがある](https://ja.stackoverflow.com/a/12005/4236)ため、使用には気を付ける必要があります。




Чайкаさんが指摘されている通り、期待値は 6/36 ですね。

そのほか指摘されていない点として

>
[code]

>     usleep(microsecond);
>  
[/code]

ウェイトを入れたところで乱数の結果は変化しません。時間の無駄となります。

>
[code]

>     double sum;
>     double average, avepro;
>     ...
>     sum += count;
>     ...
>     average = sum / (count + 1);
>  
[/code]

大きな数を扱うために`double`を選択したのでしょうか？
`double`は浮動小数点数であり大きな数を扱うことができると誤解されますが、`double`は仮数部つまり有効精度が52bitしかありません。有効精度以下の演算は丸め込まれるため、大きな数になった場合に
`sum += count` の演算は結果が変化しなくなります。結局、
**`double`は整数演算目的では52bit程度しか使えない**ことを覚えておくとよいでしょう。  
`uint64_t`もしくは`unsigned long long`の方がより大きな数を扱えます。`uint64_t`であれば64bitの整数を扱えます。

今回は関係ないようですが、[`rand()`は性能が悪く意図しない結果を引き起こすことがある](https://ja.stackoverflow.com/a/12005/4236)ため、使用には気を付ける必要があります。

