特定の試行回数の後にN個の一意の数値のセットから特定の数値が選択される確率をテストするアルゴリズムを検討します(たとえば、N = 2の場合、ルーレット(0なし)でX回の試行にかかる確率はどれくらいですか?勝つために黒?)。
このための正しい分布は、pow(1-1 / N、X-1)*(1 / N)です。
ただし、次のコードを使用してこれをテストすると、Nとは関係なく、シードとは関係なく、X=31に常に深い溝があります。
これは、使用中のPRNGの実装の詳細のために防ぐことができない本質的な欠陥ですか、これは本当のバグですか、それとも明らかな何かを見落としていますか?
// C
#include <sys/times.h>
#include <math.h>
#include <stdio.h>
int array[101];
void main(){
int nsamples=10000000;
double breakVal,diffVal;
int i,cnt;
// seed, but doesn't change anything
struct tms time;
srandom(times(&time));
// sample
for(i=0;i<nsamples;i++){
cnt=1;
do{
if((random()%36)==0) // break if 0 is chosen
break;
cnt++;
}while(cnt<100);
array[cnt]++;
}
// show distribution
for(i=1;i<100;i++){
breakVal=array[i]/(double)nsamples; // normalize
diffVal=breakVal-pow(1-1/36.,i-1)*1/36.; // difference to expected value
printf("%d %.12g %.12g\n",i,breakVal,diffVal);
}
}
libc6パッケージ2.15-0ubuntu20とIntelCorei5-2500SandyBridgeを搭載した最新のXubuntu12.10でテストしましたが、これは数年前に古いUbuntuマシンですでに発見されています。
また、Unity3D /Monoを使用してWindows7でこれをテストしました(ただし、どのMonoバージョンかはわかりません)。ここでは、System.Randomを使用するとX = 55で溝が発生しますが、Unityの組み込みのUnity.Randomには目に見える溝がありません(少なくともX <100の場合)。
配布:
違い: