|
[ 簡単な説明 ] 一様分布乱数の平均、分散、及び一様さのχ二乗検定です。 0〜1の一様分布乱数ですから、平均値は 0.5、分散は 0.833333...(=1/12) が理想値です。 17種類の擬似一様乱数関数を評価しています。 注1 : χ二乗検定のため、科学技術計算ライブラリの chi( )、qnorm( )、pnorm( )、qchi( )、pchi( )をコピーして使用しています。 注2 : プログラム中の _init 及び _func は、ヘッダファイル "random.h" 内で、定義されている配列変数で、一様乱数の初期化関数名 及び 生成関数名が、配列で定義されています。 |
/* test2.c 一様分布乱数テスト */
#include <stdio.h>
#include <stdlib.h>
#include "random.h"
#define ulong unsigned long
void error(char *s, int r);
double chi(int n);
int qnorm(double u,double *qn);
int pnorm(double qn, double *u);
int qchi(double x2, int nu, double *qc);
int pchi(double qc, int nu, double *x2);
#define N1 20 /* 分割数 */
#define N2 50 /* 分割数 */
#define N3 200 /* 分割数 */
static int flag[_M] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
main(int argc, char *argv[])
{
double ave, dn1, dn2, dn3, k1, k2, k3, kk1, kk2, kk3, m, m1, n;
double sigma1, sigma2, sigma3, x, xm, x2;
double Ave, Sigma;
double (*func)(void);
ulong b1[N1], b2[N2], b3[N3];
int i, i1, i2, i3, k;
n = (argc < 2)? 10000.: atof(argv[1]);
fprintf(stderr, "n = %.0f\n", n);
dn1 = (double)N1;
dn2 = (double)N2;
dn3 = (double)N3;
fprintf(stderr, "Now, Calcurate start!\n");
printf("個数 = %.0f 1次元分割数 = %d , %d , %d\n", n, N1, N2, N3);
k1 = chi(N1 - 1);
k2 = chi(N2 - 1);
k3 = chi(N3 - 1);
printf(" χ^2\n");
printf(" 関数 平均値 分散 分割%3d %3d %3d\n", N1, N2, N3);
for(k = 0; k < _M; k++)
{
if(flag[k])
{
for(i = 0; i < N1; i++) b1[i] = 0;
for(i = 0; i < N2; i++) b2[i] = 0;
for(i = 0; i < N3; i++) b3[i] = 0;
fprintf(stderr, "***** %s() ", _pname[k]);
Ave = Sigma = m = 0.0;
if(_init[k] != NULL) _init[k](1L);
func = _func[k];
do
{
x = func();
i1 = x * dn1;
i2 = x * dn2;
i3 = x * dn3;
b1[i1]++;
b2[i2]++;
b3[i3]++;
m1 = m++;
x -= Ave;
Ave += (xm = x / m);
Sigma += m1 * x * xm;
} while(m < n);
putc('\n', stderr);
sigma1 = sigma2 = sigma3 = 0.0;
ave = n / dn1;
for(i = 0; i < N1; i++)
{
x = b1[i] - ave;
sigma1 += x * x;
}
ave = n / dn2;
for(i = 0; i < N2; i++)
{
x = b2[i] - ave;
sigma2 += x * x;
}
ave = n / dn3;
for(i = 0; i < N3; i++)
{
x = b3[i] - ave;
sigma3 += x * x;
}
kk1 = sigma1 / n * dn1;
kk2 = sigma2 / n * dn2;
kk3 = sigma3 / n * dn3;
printf("%8s %8.6f %8.6f %6.1f %6.1f %6.1f %s %s %s\n",
_pname[k], Ave, Sigma / (n - 1.), kk1, kk2, kk3,
(kk1 < k1)? " ": "×",
(kk2 < k2)? " ": "×",
(kk3 < k3)? " ": "×");
}
}
fprintf(stderr, "Calcurate End!\n\n");
return 1;
}
void error(char *s, int r)
{
fprintf(stderr, "Error : %s\n", s);
exit(r);
}
double chi(int n)
{
static double p[8] = {0.01, 0.1, 0.5, 1., 2., 5., 10., 20.};
double c;
int j;
printf(" n α =");
for(j = 0; j < 8; j++) printf("%5.2f%% ", p[j]);
putchar('\n');
printf("%4d ", n);
for(j = 0; j < 8; j++)
{
pchi(p[j] / 100., n, &c);
printf("%8.2f", c);
}
putchar('\n');
return c;
}
int qnorm(double u,double *qn)
{
int i;
static double a[9] = { 1.24818987e-4, -1.075204047e-3,
5.198775019e-3, -1.9198292004e-2,
5.9054035642e-2, -1.51968751364e-1,
3.19152932694e-1, -5.319230073e-1,
7.97884560593e-1 },
b[15]= { -4.5255659e-5, 1.5252929e-4,
-1.9538132e-5, -6.76904986e-4,
1.390604284e-3, -7.9462082e-4,
-2.034254874e-3, 6.549791214e-3,
-1.0557625006e-2, 1.1630447319e-2,
-9.279453341e-3, 5.353579108e-3,
-2.141268741e-3, 5.35310549e-4,
9.99936657524e-1 };
double w, y, z;
if(u == 0.0) z = 0.0;
else
{
y = fabs(u) * 0.5;
if(y >= 3.0) z = 1.0;
else
{
if(y < 1.0)
{
w = y * y;
z = a[0];
for(i = 1; i < 9; i++) z = z * w + a[i];
z *= (y * 2.0);
}
else
{
y -= 2.0;
z = b[0];
for(i = 1; i < 15; i++) z = z * y + b[i];
}
}
}
if(u < 0.0) *qn = (1.0 - z) * 0.5;
else *qn = (1.0 + z) * 0.5;
return 0;
}
/* normal distribution */
int pnorm(double qn, double *u)
{
int i, j;
static double b[11]= { 0.1570796288e1, 0.3706987906e-1,
-0.8364353589e-3, -0.2250947176e-3,
0.6841218299e-5, 0.5824238515e-5,
-0.104527497e-5, 0.8360937017e-7,
-0.3231081277e-8, 0.3657763036e-10,
0.6936233982e-12 };
double w1, w2, w3;
if(qn <= 0.0 || qn >= 1.0) return 999;
if(qn == 0.5) *u = 0.0;
else
{
w1 = qn;
if(qn > 0.5) w1 = 1.0 - w1;
w2 = 4.0 * w1 * (1.0 - w1);
w3 = - log(w2);
w1 = b[0];
for(i = 1; i < 11; i++)
{
w2 = i;
w1 += (b[i] * pow(w3, w2));
}
w3 = sqrt(w1 * w3);
if(qn < 0.5) w3 = - w3;
*u = w3;
}
return 0;
}
/* chi-square distribution */
int qchi(double x2, int nu, double *qc)
{
double f, w, pw, x, qw, a, a1, a2;
if(nu < 1) return 999;
if(x2 <= 0.0) *qc = 1.0;
else if(x2 > 400.0) *qc = 0.0;
else if(nu > 10)
{
f = nu;
w = 2.0 / (9.0 * f);
pw = pow(x2 / f, 1.0 / 3.0);
x = (pw - 1.0 + w) / sqrt(w);
qnorm(x, &qw);
*qc = 1.0 - qw;
}
else
{
w = exp(- x2 / 2.0);
x = sqrt(x2);
if((nu % 2) == 0)
{
a1 = 2.0;
*qc = w;
if(nu == 2) return 0;
}
else
{
qnorm(x, &qw);
*qc = 2.0 * (1.0 - qw);
if(nu == 1) return 0;
a1 = 1.0;
w = 0.797884560750774 * w / x;
}
a2 = nu - 2;
for(a = a1; a <= a2; a += 2.0)
{
w *= (x2 / a);
*qc += w;
}
}
return 0;
}
/* chi-square distribution */
int pchi(double qc, int nu, double *x2)
{
int i, j;
double f, u, w, w1, w2, c, c1, c2, c3, gam, x, y, qch, wx;
if(qc <= 0.0 || qc >= 1.0 || nu < 1) return 999;
if(nu == 1)
{
w1 = qc * 0.5;
pnorm(w1, &u);
*x2 = u * u;
}
else if(nu == 2) *x2 = - 2.0 * log(qc);
else
{
f = nu;
pnorm(qc, &u);
u = - u;
if(nu > 10)
{
w1 = sqrt(2.0 * f);
w2 = u * u;
c1 = f + w1 * u + 2.0 * (w2 - 1.0) / 3.0;
c2 = (w2 - 7.0) * u / (9.0 * w1);
c3 = ((3.0 * w2 + 7.0) * w2 - 16.0) * 2.0 / (405.0 * f);
wx = c1 + c2 - c3;
if(wx < 0.0) wx = 0.0;
}
else
{
w = 2.0 / (9.0 * f);
w = 1.0 - w + u * sqrt(w);
wx = f * w * w * w;
if(wx < 0.0) wx = 0.0;
if((nu % 2) == 0) gam = 1.0;
else gam = 1.772453850905516;
j = (nu + 1) / 2 - 1;
w = f / 2.0;
for(i = 1; i <= j; i++)
{
c = i;
gam *= (w - c);
}
x = wx / 2.0;
y = w - 1.0;
c1 = pow(x, y);
c2 = exp(-x) / 2.0;
c3 = c1 * c2;
qchi(wx, nu, &qch);
wx += ((qch - qc) * gam / c3);
}
*x2 = wx;
}
return 0;
}
|
個数 = 10000 1次元分割数 = 20 , 50 , 200
n α = 0.01% 0.10% 0.50% 1.00% 2.00% 5.00% 10.00% 20.00%
19 50.77 43.81 38.58 36.19 33.69 30.14 27.20 23.90
49 94.59 85.35 78.23 74.92 71.41 66.34 62.04 57.08
199 281.87 266.39 254.13 248.33 242.08 232.91 224.96 215.57
χ^2
関数 平均値 分散 分割 20 50 200 時間[sec]
urnd0 0.504872 0.083440 20.5 46.8 196.5 1.516
urnd1 0.495858 0.084288 23.1 66.4 209.4 1.500 ×
urnd2 0.499196 0.083227 20.2 38.9 183.6 1.516
urnd3 0.503982 0.083137 13.3 46.8 192.9 1.500
urnd4 0.498005 0.084786 24.0 57.9 195.8 1.531 × ×
urnd5 0.497543 0.083469 18.5 36.1 206.9 1.563
urnd6 0.496068 0.082186 17.2 41.8 186.7 1.500
mrnd 0.496310 0.084270 18.5 42.3 210.6 1.531
rrnd 0.498968 0.083952 22.7 41.6 179.0 2.094
ornd0 0.499616 0.083963 25.0 70.5 238.6 1.563 × × ×
ornd1 0.495985 0.082711 24.2 43.9 198.6 1.578 ×
ornd2 0.500468 0.083656 10.0 35.7 203.2 1.563
brnd 0.499566 0.083800 24.7 69.3 237.9 1.672 × × ×
ernd 0.501506 0.082683 21.5 32.1 180.5 1.844
krnd 0.501401 0.084116 27.8 69.0 230.0 1.563 × × ×
drnd 0.505637 0.082814 15.1 44.5 240.2 1.953 ×
qrnd 0.501766 0.083250 14.8 50.5 192.9 1.516
個数 = 100000 1次元分割数 = 20 , 50 , 200
n α = 0.01% 0.10% 0.50% 1.00% 2.00% 5.00% 10.00% 20.00%
19 50.77 43.81 38.58 36.19 33.69 30.14 27.20 23.90
49 94.59 85.35 78.23 74.92 71.41 66.34 62.04 57.08
199 281.87 266.39 254.13 248.33 242.08 232.91 224.96 215.57
χ^2
関数 平均値 分散 分割 20 50 200 時間[sec]
urnd0 0.500248 0.083326 14.9 53.0 186.1 15.672
urnd1 0.500668 0.083258 13.1 41.9 196.1 15.719
urnd2 0.499322 0.083636 18.5 53.3 207.0 15.734
urnd3 0.500502 0.083408 11.8 43.9 196.0 15.813
urnd4 0.501603 0.083232 30.0 82.9 220.2 15.766 × × ×
urnd5 0.499909 0.083222 15.7 35.2 175.3 15.766
urnd6 0.500882 0.083323 16.7 57.1 226.4 15.656 × ×
mrnd 0.500605 0.083535 26.4 45.2 184.7 16.078 ×
rrnd 0.499971 0.083636 13.2 36.7 167.9 21.594
ornd0 0.499398 0.083541 17.3 54.5 210.9 16.469
ornd1 0.498780 0.083248 10.2 27.8 168.7 16.609
ornd2 0.499891 0.083125 17.5 45.3 215.5 16.391
brnd 0.499425 0.083529 17.3 54.3 210.3 17.438
ernd 0.499511 0.083275 23.1 50.4 212.4 19.078
krnd 0.500453 0.083304 9.7 32.8 164.8 16.078
drnd 0.501743 0.083057 21.0 52.6 214.4 20.547
qrnd 0.500728 0.083220 9.5 45.7 179.7 15.703
個数 = 1000000 1次元分割数 = 20 , 50 , 200
n α = 0.01% 0.10% 0.50% 1.00% 2.00% 5.00% 10.00% 20.00%
19 50.77 43.81 38.58 36.19 33.69 30.14 27.20 23.90
49 94.59 85.35 78.23 74.92 71.41 66.34 62.04 57.08
199 281.87 266.39 254.13 248.33 242.08 232.91 224.96 215.57
χ^2
関数 平均値 分散 分割 20 50 200 時間[sec]
urnd0 0.500195 0.083217 11.8 60.7 225.4 157.266 × ×
urnd1 0.499969 0.083301 24.5 51.9 214.2 157.391 ×
urnd2 0.499932 0.083501 19.5 48.8 197.9 158.297
urnd3 0.500188 0.083333 14.3 37.7 153.4 158.625
urnd4 0.500206 0.083253 16.0 52.4 223.1 158.469 ×
urnd5 0.499896 0.083317 8.1 52.0 213.3 158.047
urnd6 0.500172 0.083322 25.9 62.6 238.9 157.453 × × ×
mrnd 0.499962 0.083316 21.8 59.7 203.4 161.391 ×
rrnd 0.500631 0.083335 25.5 61.2 201.3 216.969 × ×
ornd0 0.500256 0.083361 29.0 56.5 204.5 165.781 ×
ornd1 0.499637 0.083363 21.5 54.8 229.1 167.125 ×
ornd2 0.499792 0.083280 9.7 26.5 182.2 164.844
brnd 0.500254 0.083360 29.0 56.3 204.0 175.281 ×
ernd 0.500158 0.083377 8.2 30.6 168.3 192.109
krnd 0.500007 0.083374 10.5 42.9 230.0 161.484 ×
drnd 0.500598 0.083415 25.3 45.6 186.7 206.406 ×
qrnd 0.500116 0.083388 23.4 55.5 234.1 157.891 ×
個数 = 1000000 1次元分割数 = 20 , 50 , 200
n α = 0.01% 0.10% 0.50% 1.00% 2.00% 5.00% 10.00% 20.00%
19 50.77 43.81 38.58 36.19 33.69 30.14 27.20 23.90
49 94.59 85.35 78.23 74.92 71.41 66.34 62.04 57.08
199 281.87 266.39 254.13 248.33 242.08 232.91 224.96 215.57
χ^2
関数 平均値 分散 分割 20 50 200 時間[sec]
urnd0 0.500195 0.083217 11.8 60.7 225.4 148.891 × ×
urnd1 0.499969 0.083301 24.5 51.9 214.2 148.813 ×
urnd2 0.499932 0.083501 19.5 48.8 197.9 149.797
urnd3 0.500188 0.083333 14.3 37.7 153.4 149.609
urnd4 0.500206 0.083253 16.0 52.4 223.1 149.203 ×
urnd5 0.499896 0.083317 8.1 52.0 213.3 149.031
urnd6 0.500172 0.083322 25.9 62.6 238.9 149.578 × × ×
mrnd 0.499962 0.083316 21.8 59.7 203.4 152.203 ×
rrnd 0.499827 0.083391 21.9 56.3 223.7 238.766 ×
ornd0 0.500256 0.083361 29.0 56.5 204.5 159.828 ×
ornd1 0.499637 0.083363 21.5 54.8 229.1 160.094 ×
ornd2 0.499792 0.083280 9.7 26.5 182.2 158.813
brnd 0.500254 0.083360 29.0 56.3 204.0 171.094 ×
ernd 0.500158 0.083377 8.2 30.6 168.3 184.969
krnd 0.500007 0.083374 10.5 42.9 230.0 156.125 ×
drnd 0.500598 0.083415 25.3 45.6 186.7 213.766 ×
qrnd 0.500116 0.083388 23.4 55.5 234.1 150.406 ×
|