|
[ 簡単な説明 ] 正規分布乱数の平均、標準偏差、及び正規度のχ二乗検定です。正規分布の平均値は 0、標準偏差は 1.0 が理想値です。 正規分布乱数生成関数内で使用する一様分布乱数関数に、ライブラリ中の17種類の一様分布乱数関数を適用して評価しています。 注1 : χ二乗検定のため、科学技術計算ライブラリの chi( )、qnorm( )、pnorm( )、qchi( )、pchi( )をコピーして使用しています。 注2 : プログラム中の _init 及び _func は、ヘッダファイル "random.h" 内で、定義されている配列変数で、一様乱数の初期化関数名 及び 生成関数名が、配列で定義されています。 |
/* test3.c 正規分布乱数の検定(Random number of Normal Distribution) */
#include <stdio.h>
#include <stdlib.h>
#include "random.h"
#define N 50 /* 分割数 - 2 */
double qnorm(double u);
double pnorm(double qn);
double qchi(double x2, int n);
double pchi(double qc, int n);
main(int argc, char *argv[])
{
double av, st, ave, du, m, m1, q, q0, u, sigma, x, x2, x2a, x2b, x2c, xm, w;
double p[N + 2];
int i, i1, i2, j, k, loop, n, nmax = N + 1, n10;
int b[N + 2], f[N + 2];
n = (argc < 2)? 10000: atoi(argv[1]);
if (n < 10) n = 10000;
n10 = n / 10;
av = (double)N / 2. + 1.;
st = (double)N / 10.;
du = 1. / st;
for(i = N / 2 + 1, u = du, q0 = 0.5; i <= N; i++)
{
q = qnorm(u);
p[i] = q - q0;
q0 = q;
u += du;
}
p[i] = 1. - q;
for(i = N / 2 + 1; i <= N + 1; i++) p[N + 1 - i] = p[i];
printf("個数 = %10d 棄却水準 χo^2\n", n);
printf("関数\t平均値 標準偏差 χ^2 [ 1%% 0.1%% 0.01%% ]\n");
for(loop = 0; loop < _M; loop++)
{
fprintf(stderr, "*** %s start ", _pname[loop]);
init_gaussd(_init[loop], _func[loop], 0);
ave = sigma = m = 0.0;
for(i = 0; i <= N + 1; i++) b[i] = 0.0;
while(m < n)
{
x = gaussd(0., 1.);
i = (int)(x * st + av);
if(i < 0) i = 0;
else if(i > nmax) i = nmax;
b[i]++;
m1 = m++;
ave += (xm = (x -= ave) / m);
sigma += m1 * x * xm;
if((int)m % n10 == 0) putc('.', stderr);
}
fprintf(stderr, " test start");
/* 検定 */
for(i = 0; i <= N + 1; i++) f[i] = (int)((double)n * p[i]);
i1 = 0;
i2 = N + 1;
for(i = N / 2; i >= 0; i--)
{
if(b[i] < 5)
{
i1 = i + 1;
for(j = k = 0; i >= 0; i--)
{
j += b[i];
k += f[i];
b[i] = f[i] = 0;
}
b[i1] += j;
f[i1] += k;
break;
}
}
for(i = N / 2 + 1; i <= N + 1; i++)
{
if(b[i] < 5)
{
i2 = i - 1;
for(j = k = 0; i <= N + 1; i++)
{
j += b[i];
k += f[i];
b[i] = f[i] = 0;
}
b[i2] += j;
f[i2] += k;
break;
}
}
x2 = 0.;
for(i = i1; i <= i2; i++)
{
w = (double)(b[i] - f[i]);
x2 += (w * w / (double)f[i]);
}
putc('\n', stderr);
x2a = pchi(0.01, i2 - i1);
x2b = pchi(0.001, i2 - i1);
x2c = pchi(0.0001, i2 - i1);
printf("%s\t%11.8f %11.8f (%8.2f) [ %6.2f %6.2f %6.2f ]\n",
_pname[loop], ave, sqrt(sigma / m1), x2, x2a, x2b, x2c);
}
fprintf(stderr, "***** end of test3 *****\n");
return 1;
}
double qnorm(double u)
{
static double a[9] = { 1.24818987e-4, -1.075204047e-3, 5.198775019e-3,
-0.019198292004, 0.059054035642,-0.151968751364,
0.319152932694,-0.5319230073, 0.797884560593};
static double 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,-0.010557625006,
0.011630447319,-9.279453341e-3, 5.353579108e-3,
-2.141268741e-3, 5.35310549e-4, 0.999936657524};
double w, y, z;
int i;
if(u == 0.) return 0.5;
y = u / 2.;
if(y < -6.) return 0.;
if(y > 6.) return 1.;
if(y < 0.) y = - y;
if(y < 1.)
{
w = y * y;
z = a[0];
for(i = 1; i < 9; i++) z = z * w + a[i];
z *= (y * 2.);
}
else
{
y -= 2.;
z = b[0];
for(i = 1; i < 15; i++) z = z * y + b[i];
}
if(u < 0.) return (1. - z) / 2.;
return (1. + z) / 2.;
}
double pnorm(double qn)
{
static double b[11] = { 1.570796288, 0.03706987906, -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, w3;
int i;
if(qn < 0. || 1. < qn)
{
fprintf(stderr, "Error : qn <= 0 or qn >= 1 in pnorm()!\n");
return 0.;
}
if(qn == 0.5) return 0.;
w1 = qn;
if(qn > 0.5) w1 = 1. - w1;
w3 = -log(4. * w1 * (1. - w1));
w1 = b[0];
for(i = 1; i < 11; i++) w1 += (b[i] * pow(w3, (double)i));
if(qn > 0.5) return sqrt(w1 * w3);
return -sqrt(w1 * w3);
}
double qchi(double x2, int n)
{
double w, pw, x, qc;
int i, i1;
if(n < 1)
{
fprintf(stderr,"Error : 自由度 < 1 in qchi()!\n");
return 0.;
}
if(x2 <= 0.) return 1.;
if(x2 > 400.) return 0.;
if(n > 10)
{
w = 2. / (9. * (double)n);
pw = pow(x2 / (double)n, 1. / 3.);
return 1. - qnorm((pw - 1. + w) / sqrt(w));
}
w = exp(-x2 / 2.);
if(n == 2) return w;
x = sqrt(x2);
if(n == 1) return 2. * (1. - qnorm(x));
if((n % 2) == 0)
{
i1 = 2;
qc = w;
}
else
{
i1 = 1;
qc = 2. * (1. - qnorm(x));
w *= (0.797884560750774 / x);
}
for(i = i1; i <= n - 2; i += 2)
{
w *= (x2 / (double)i);
qc += w;
}
return qc;
}
double pchi(double qc, int n)
{
double c1, c2, gam, x, w, wx;
int i, j;
if(qc <= 0. || qc >= 1. || n < 1)
{
fprintf(stderr,"Error : Illigal parameter in pchi()!\n");
return 0.;
}
if(n == 1)
{
w = pnorm(qc / 2.);
return w * w;
}
if(n == 2) return -2. * log(qc);
x = -pnorm(qc);
if(n > 10)
{
w = x * x;
wx = sqrt(2. * (double)n);
c1 = (w - 7.) * x / 9. / wx;
c2 = ((3. * w + 7.) * w - 16.) * 2. / 405. / (double)n;
wx = (double)n + wx * x + 2. * (w - 1.) / 3. + c1 - c2;
if(wx < 0.) return 0.;
return wx;
}
w = 2. / 9. / (double)n;
w = 1. - w + x * sqrt(w);
wx = (double)n * w * w * w;
if((n % 2) == 0) gam = 1.;
else gam = 1.772453850905516;
j = (n + 1) / 2 - 1;
w = (double)n / 2.;
for(i = 1; i <= j; i++) gam *= (w - (double)i);
x = wx / 2.;
c1 = pow(x, w - 1.);
c2 = exp(-x) / 2.;
return wx + (qchi(wx, n) - qc) * gam / c1 / c2;
}
|
個数 = 10000 棄却水準 χo^2 関数 平均値 標準偏差 χ^2 [ 1% 0.1% 0.01% ] urnd0 -0.01157873 1.01102622 ( 70.83) [ 54.77 63.86 72.02 ] urnd1 0.01111361 0.99500596 ( 37.93) [ 52.19 61.09 69.09 ] urnd2 -0.01134527 0.98991551 ( 25.05) [ 50.89 59.70 67.62 ] urnd3 -0.00029358 0.98893708 ( 41.93) [ 52.19 61.09 69.09 ] urnd4 0.00171692 1.00420321 ( 53.19) [ 52.19 61.09 69.09 ] urnd5 0.00427380 1.00442877 ( 25.78) [ 52.19 61.09 69.09 ] urnd6 0.00913833 0.99144382 ( 39.74) [ 50.89 59.70 67.62 ] mrnd -0.00882541 1.00779210 ( 22.00) [ 50.89 59.70 67.62 ] rrnd -0.00399233 0.99839060 ( 263.14) [ 45.64 54.04 61.64 ] ornd0 0.00572074 0.98281339 ( 32.85) [ 50.89 59.70 67.62 ] ornd1 -0.01090574 1.00490025 ( 53.71) [ 52.19 61.09 69.09 ] ornd2 -0.01035353 1.00630319 ( 30.00) [ 52.19 61.09 69.09 ] brnd 0.00596488 0.98253856 ( 32.61) [ 50.89 59.70 67.62 ] ernd -0.00198195 1.01016617 ( 43.14) [ 52.19 61.09 69.09 ] krnd 0.01376447 0.98840755 ( 24.43) [ 49.59 58.29 66.14 ] drnd -0.01603079 0.99878163 ( 40.54) [ 50.89 59.70 67.62 ] qrnd -0.01713232 1.00325385 ( 38.83) [ 53.48 62.48 70.56 ] |