#include<stdio.h>
#define N 10000 //生成する一様乱数の個数
#define M 10 //区間分けの個数
#define P(z) z
void frequency(double *x,int *f);//観測度を求める
void expected_frequency(int *e); //期待度数を求める
double x2_test(int *e,int *f); //カイ2乗を求める
int main(void){
int i;
int f[M],e[M]; //f:観測度数 e:期待度数
double a=1229,c=351750,s=300,m=1664501,x2,b;// x2:カイ2乗の値 b:分散
double r[N],x[N],sum=0.0,sum2=0.0; //x:一様乱数 r:数列
for(i=0;i<M;i++){ //配列の初期化
f[i]=0;
}
//一様乱数の生成
r[0]=s;
x[0]=r[0]/m;
for(i=1;i<N;i++){
r[i]=(int)(a*r[i-1]+c)%(int)m;
x[i]=r[i]/m;
}
//平均と分散の計算
for(i=0;i<N;i++){
sum+=x[i];
printf("x[%d]=%f\n",i,x[i]);//乱数の表示
sum2+=x[i]*x[i];
}
b=sum2/N-(sum/N*sum/N);
printf("平均=%f 分散=%f\n",sum/N,b);
frequency(x,f); //観測度数の呼び出し
expected_frequency(e); //期待度数の呼び出し
printf("カイ2乗=%f\n",x2_test(e,f));
for(i=0;i<M;i++){
printf("%d\n",f[i]);//区間ごとの個数の表示
}
return 0;
}
void frequency(double *x,int *f){ //配列はポインタでしか渡せないのでポインタを使う?
int i,k=0,z=0;
double j=0;
while(j<1.0){
for(i=0;i<N;i++){
if(x[i]>=j && x[i]<j+1.0/M){ //範囲内の数ならばkをインクリメントし
k++; //観測度数を求める
}
}
f[z]=k; //求めた観測度数を配列に入れる
k=0;
z++; //区間をカウントしている
j=j+1.0/M;
}
}
void expected_frequency(int *e){
int i=0,j=0,sum=0;
for(i=0;i<M;i++){
e[i]=N*(P(j+1.0/M)-P(j)); //区間[a,b],確率分布関数がP(x)のときの,
j+=1.0/M; //期待度数の求め方,N*{P(b)-P(a)}を計算する
sum+=e[i];
}
}
double x2_test(int *e,int *f){
int i;
double x2;
for(i=0;i<M;i++){
x2+=((double)f[i]-(double)e[i])*((double)f[i]-(double)e[i])/(double)e[i]; //カイ2乗を計算
}
return x2; //カイ2乗の値を返す
}
合同式法により、区間0≦x<1の一様分布に従う疑似乱数を生成し、1次元適合度検定のためカイ2乗統計量を計算するプログラム(計算式は下に)です。
これにコメント文等でこのプログラムの説明をせよと言われたのですが分からないところがあります。(ある程度は自分で書きました)
1つは最初の#define P(z) z の部分はどう使われているのか
2つはr=(int)(a*r[i-1]+c)%(int)m; の(int)はなぜ必要なのか
3つ目は関数で使われている変数jとsumがどう使われているかです。
「計算式」
一様乱数の求め方の部分は(int)の必要性以外は理解できたので省略します。
カイ2乗の求め方は、
カイ2乗=Σ_k=1 ^M (f_k-e_k)^2/e_k です
(わかりにくいですがΣの下がk=1,上がM,_は下付きの文字です)
f_kは観測度数、e_kは期待度数です。
生成した乱数を10個の区間に分けて、0~0.1の区間の乱数の個数、0.1~0.2の区間の乱数の個数と計算して、
それぞれの区間に何個乱数ができたのかが観測度数、
期待度数は
連続的確率密度関数がp(x),p(x)の確率分布関数がP(x)とする。このとき、区間[a,b]の期待度数e_a,b はNを総標本数とすると
e_a,b=N×{P(b)-P(a)}
と求められます。
わかりにくいと思うのでこのサイトを見てください→http://ja.wikipedia.org/wiki/%E3%82%AB% ... C%E5%AE%9A
長文失礼しました
その他これ違うというところがあったら教えてくださると助かります。