Random Number 1
/*
1
/*
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
unsigned long int next = 423758209;
double rand0_1(void);
main(void)
{
int i;
for(i=0;i<=10;i++)
{
printf("%d %lf\n", i,(double)rand0_1());
}
return 0;
}
double rand0_1(void)
{
next = next*19 % 423325498;
return((double)next/(double)423325498.);
}
void srand0_1(unsigned int seed)
{
next = seed;
}
実行結果
0 0.873641 1 0.453407 2 0.614738 3 0.534233 4 0.004652 5 0.088385 6 0.679320 7 0.761296 8 0.318850 9 0.058149 10 0.104833
Random Number 2
/*
NUMERICAL RECIPE IN C P204
一様乱数(線形合同法)
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
unsigned long next = 1;
int rand(void);
int main(void)
{
int i;
for(i=0;i<=10;i++)
{
printf("%d %ld\n", i,rand());
}
return 0;
}
int rand(void)
{
next = next*1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
void srand(unsigned int seed)
{
next = seed;
}
実行結果
0 16838 1 38526 2 10113 3 50283 4 63819 5 38395 6 55778 7 40187 8 48980 9 4086 10 2749
/*
一様乱数(線形合同法) Part II
x_n=(A x_{n-1} + C) mod M
Mが2^n, A が8で割って余り5の数、Cが奇数という条件で、
0-M-1までの整数が周期Mで1回ずつ現れる。
A=109,C=1021, M=32768, x_0=13
*/
#include <stdio.h>
unsigned rndnum=13; /*乱数の初期値*/
unsigned irnd();
main()
{
int j;
for (j=0;j<10;j++){
printf("%d\n", irnd());
}
}
unsigned irnd(void) /*0-32767 の整数乱数*/
{
rndnum=(rndnum*109+1021)%32768;
return rndnum;
}
実行結果
2438 4619 12972 5945 26434 31511 27848 21797 17598 18659
Random Number 3
/* Park and Miller の乱数生成ルーチン(numerical recippes p206) */
/* #define idum = (seed) としておいて、
main の方でも忘れずにfloat rand0_1(long *);と宣言する
本文のほうでは rand0_1(&idum) と使う。
*/
#include <stdio.h>
#include <math.h>
#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define MASK 123459876
unsigned long int idum = 2048;
float ran0(long *);
int main(void)
{
int i;
for(i=0;i<=10;i++)
{
printf("%d %lf\n", i,ran0(&idum));
}
return 0;
}
float ran0(long *idum)
{
long k;
float ans;
*idum ^= MASK;
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
ans=AM*(*idum);
*idum ^= MASK;
return ans;
}
実行結果
idum = 1024 0 0.250592 1 0.708165 2 0.122989 3 0.072388 4 0.621420 5 0.207334 6 0.657995 7 0.922808 8 0.631353 9 0.156461 10 0.638768 idum = 2048 0 0.226550 1 0.624079 2 0.903439 3 0.099183 4 0.960467 5 0.564713 6 0.136934 7 0.450398 8 0.832795 9 0.779885 10 0.520386
Random Number 4
/*
NUMERICAL RECIPE IN C P207-8
Park and Millerの「最小」乱数生成法とBaye-Durhamの
切り混ぜに安全機構を付けたもの。0.0と1.0の間(両端を
除く)の一様乱数を返す。初期化にはidumを負の値にして
呼び出す。それ以降は呼び出しごとにidumを変えては
ならない。RNMXはほぼ1未満の最大の浮動小数点とする。
*/
#include <stdio.h>
#include <math.h>
#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define NTAB 32
#define NDIV (1+(IM-1)/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)
unsigned long int idum =1024;
float ran1(long *);
int main(void)
{
int i;
for(i=0;i<=10;i++)
{
printf("%d %f\n", i,ran1(&idum));
}
return 0;
}
float ran1(long *idum)
{
int j;
long k;
static long iy=0;
static long iv[NTAB];
float temp;
if(*idum <= 0 || !iy){
if(-(*idum) < 1) *idum =1;
else *idum = -(*idum);
for (j=NTAB +7;j>=0; j--){
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
if( j < NTAB) iv[j]=*idum;
}
iy=iv[0];
}
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
j=iy/NDIV;
iy=iv[j];
iv[j]= *idum;
if((temp=AM*iy) > RNMX) return RNMX;
else return temp;
}
実行結果
0 0.415999 1 0.091965 2 0.756410 3 0.529700 4 0.930436 5 0.383502 6 0.653919 7 0.066842 8 0.722660 9 0.671149 10 0.383416
Random Number 5
/*
NUMERICAL RECIPE IN C P210
0.0と1.0の間の一様乱数を返す。乱数列を初期化、再初期化
するにはidumを任意の負の値にする。
*/
#include <stdio.h>
#include <math.h>
#define MBIG 1000000000
#define MSEED 161803398
#define MZ 0
#define FAC (1.0/MBIG)
unsigned long int idum =1024;
float ran3(long *);
int main(void)
{
int i;
for(i=0;i<=10;i++)
{
printf("%d %f\n", i,ran3(&idum));
}
return 0;
}
float ran3(long *idum)
{
static int inext, inextp;
static long ma[56];
static int iff=0;
long mj, mk;
int i,ii,k;
if(*idum < 0 || iff == 0){
iff=1;
mj=MSEED-(*idum < 0 ? -*idum : *idum);
mj %=MBIG;
ma[55]=mj;
mk=1;
for(i=1; i<=54; i++){
ii=(21*i) % 55;
ma[ii]=mk;
mk=mj-mk;
if(mk < MZ) mk += MBIG;
mj=ma[ii];
}
for(k=1; k<4;k++)
for(i=1; i<=55;i++){
ma[i] -= ma[1+(i+30) % 55];
if(ma[i] < MZ) ma[i] += MBIG;
}
inext=0;
inextp=31;
*idum=1;
}
if(++inext == 56) inext=1;
if(++inextp == 56) inext=1;
mj=ma[inext] - ma[inextp];
if(mj < MZ) mj += MBIG;
ma[inext]=mj;
return mj*FAC;
}
実行結果
0 0.461475 1 0.633433 2 0.846511 3 0.096041 4 0.353360 5 0.450735 6 0.639113 7 0.630816 8 0.662777 9 0.684881 10 0.103685
Normal Random Numbers (正規乱数)
Random Number 1
/*
Numerical Recipe in C, p.217
正規乱数
Box-Muller Method
平均0、分散1の正規分布の乱数。
*/
#include <stdio.h>
#include <math.h>
#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define NTAB 32
#define NDIV (1+(IM-1)/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)
unsigned long int idum =1024;
float gasdev(long *);
float ran1(long *);
int main(void)
{
int i;
double x;
for(i=0;i<=20;i++)
{
x=gasdev(&idum);
printf("%d %f\n", i, x );
}
return 0;
}
float gasdev(long *idum)
{
float ran1(long *);
static int iset=0;
static float gset;
float fac,rsq,v1,v2;
if (iset==0){
do {
v1=2.0*ran1(idum)-1.0;
v2=2.0*ran1(idum)-1.0;
rsq=v1*v1+v2*v2;
} while (rsq>=1.0 || rsq == 0.0);
fac=sqrt(-2.0*log(rsq)/rsq);
gset=v1*fac;
iset=1;
return v2*fac;
} else {
iset=0;
return gset;
}
}
float ran1(long *idum)
{
int j;
long k;
static long iy=0;
static long iv[NTAB];
float temp;
if(*idum <= 0 || !iy){
if(-(*idum) < 1) *idum =1;
else *idum = -(*idum);
for (j=NTAB +7;j>=0; j--){
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
if( j < NTAB) iv[j]=*idum;
}
iy=iv[0];
}
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
j=iy/NDIV;
iy=iv[j];
iv[j]= *idum;
if((temp=AM*iy) > RNMX) return RNMX;
else return temp;
}
実行結果
0 -0.836854 1 -0.172280 2 0.187118 3 1.615440 4 -0.176774 5 0.653145 6 -0.546364 7 0.194146 8 0.925709 9 1.204321 10 1.530555 11 -1.355560 12 0.051489 13 1.020178 14 -1.226161 15 0.708497 16 0.871673 17 -0.789721 18 0.332079 19 0.205602 20 -0.169367
Random Number 2
/*正規乱数(normal random numbers)
f(x)=\frac{1}{\sqrt{2\pi}\sigma}\exp{\frac{-(x-\mu)^2}{2\sigma^2}}
expected value: \mu, variance \sigma^2
*/
#include
#include
#include
#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define MASK 123459876
double normrnd(void);
double norminv(double a);
unsigned long int idum = 2048;
float ran0(long *);
main()
{
int i,numrnd;
double a;
numrnd=10;
for(i=1;i<=numrnd;i++)
{
a=normrnd();
printf("%d %f\n",i, a);
}
return ;
}
double normrnd(void)
{
double a,b;
a=ran0(&idum);
b=norminv(a);
return b;
}
double norminv(double u)
{
double a,b,w,z;
z=-log(4.0*u*(1.0-u));
a=z*(2.0611786-5.7262204/(z+11.640595));
w=sqrt(a);
if(u<0.5)b=-w;
else b=w;
return b;
}
float ran0(long *idum)
{
long k;
float ans;
*idum ^= MASK;
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
ans=AM*(*idum);
*idum ^= MASK;
return ans;
}
実行結果
1 -0.750252 2 0.316090 3 1.301970 4 -1.286779 5 1.756900 6 0.162855 7 -1.094540 8 -0.124598 9 0.965464 10 0.771815
Binomial Random Numbers (2項乱数)
Random Number 1
/*
例)
表の出る確率がp, 裏の出る確率がq=1-pであるコインを投げて、表が出ると1点、
裏が出ると0点とする。このコインをn回投げる。このときの合計点をXとすると、
取りうる値はx=0,1,2,\cdots,nですが、各点に対する確率は,
f(x)=nCxp^xq^{n-x}=nCxp^x(1-p)^{n-x}
で与えられる。
expected value: \mu=p, variance : \sigma^2 = n p(1-p)
*/
#include
#include
#include
#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define MASK 123459876
int birnd(int n,float p);
int bern(float p);
unsigned long int idum = 2048;
float ran0(long *);
main()
{
int i,k,n,numrnd;
float p;
numrnd=10;
n=5;
p=0.5;
for(i=1;i<=numrnd;i++)
{
k=birnd(n,p);
printf("%d %d\n",i, k);
}
return;
}
int birnd(int n,float p)
{
int i,k;
k=0;
for(i=1;i<=n;i++)k=k+bern(p);
return k;
}
int bern(float p)
{
int j;
double a;
a=ran0(&idum);
if(a<p)j=1;
else j=0;
return j;
}
float ran0(long *idum)
{
long k;
float ans;
*idum ^= MASK;
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
ans=AM*(*idum);
*idum ^= MASK;
return ans;
}
実行結果
1 2 2 2 3 2 4 5 5 3 6 2 7 1 8 1 9 5 10 4
Poisson Random Numbers (ポアソン乱数)
Random Number 1
/*
一定量のウランのような半減期の長い元素があったとし、一定の観測時間内に
何個の原子が崩壊するかについての分布を考える。
個々の原子が観測時間内に崩壊する確率は非常に小さいのですが、
非常に多くの原子があるため、適当な長さの観測時間を取ればその時間内
にいくつかの原子の崩壊が記録される。
このように2項分布において、対象となるnが大きいが、起こる確率(生起確率)
pが小さく両方が釣り合って n p = \lambda を満足するケースを考える。
この場合、Xの確率分布を2項分布から求めることは非常に困難ですが、
n -> \infty, p -> 0 となった極限の分布は Poissonの小数の法則から
f(x)=e^{-\lambda} \lambda^x/x!
となる。
その他にも、事故の発生件数、不良品数、突然変異数などの事象に当てはまると言われている。
expected value=variance = \lambda
*/
#include
#include
#include
#include
#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define MASK 123459876
int pornd(double a);
double exprnd(double a);
unsigned long int idum = 2048;
float ran0(long *);
main()
{
int i,numrnd;
double a;
srand((unsigned)time(NULL));
numrnd=10;
for(i=1;i<=numrnd;i++){
a=pornd(3);
printf("%d %f\n",i, a);
}
return;
}
int pornd(double t)
{
double t1;
int k;
k=0;
t1=exprnd(1);
while(t1<t){
k=k+1;
t1=t1+exprnd(1);
}
return k;
}
double exprnd(double a)
{
double b,c;
b=ran0(&idum);
c=-(1/a)*log(b);
return c;
}
float ran0(long *idum)
{
long k;
float ans;
*idum ^= MASK;
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
ans=AM*(*idum);
*idum ^= MASK;
return ans;
}
実行結果
1 1.484790 2 0.471478 3 0.101547 4 2.310794 5 0.040336 6 0.571437 7 1.988256 8 0.797625 9 0.182968 10 0.248609
Exponential Random Numbers (指数乱数)
Random Number 1
/*
例)
放射性の原子があり、この原始が崩壊するまでの時間の分布
f(x)=a e^{-ax}
F(x)=1-e^{-ax}
expected value : \mu=\frac{1}{a},
variance : \sigma^2=\frac{1}{a^2}=\mu^2
*/
#include
#include
#include
#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define MASK 123459876
double exprnd(double a);
unsigned long int idum = 2048;
float ran0(long *);
main()
{
int i,numrnd;
double a;
numrnd=10;
for(i=1;i<=numrnd;i++)
{
a=exprnd(1);
printf("%d %f\n",i, a);
}
return;
}
double exprnd(double a)
{
double b,c;
b=ran0(&idum);
c=-(1/a)*log(b);
return c;
}
float ran0(long *idum)
{
long k;
float ans;
*idum ^= MASK;
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-IR*k;
if (*idum < 0) *idum += IM;
ans=AM*(*idum);
*idum ^= MASK;
return ans;
}
実行結果
1 1.484790 2 0.471478 3 0.101547 4 2.310794 5 0.040336 6 0.571437 7 1.988256 8 0.797625 9 0.182968 10 0.248609
Test the Random Numbers
/*
一様性のテスト
*/
#include <stdio.h>
#define N 1000 /*乱数の発生回数*/
#define M 10 /*整数乱数の範囲*/
#define F (N/M) /*期待値*/
#define SCALE (40.0/F) /*ヒストグラムの高さ(自動スケール)*/
unsigned rndnum=13;
unsigned irnd();
double rnd();
main()
{
int i,j,rank,hist[M+1];
double e=0.0;
for (i=1;i<=M;i++)
hist[i]=0;
for (i=0;i<N;i++){
rank=(int)(M*rnd()+1); /*1-M の乱数を1つ発生*/
hist[rank]++;
}
for (i=1;i<=M;i++){
printf("%3d:%3d", i, hist[i]);
for (j=0;j<hist[i]*SCALE;j++) /*ヒストグラムの表示*/
printf("*");
printf("\n");
e=e+(double)(hist[i]-F)*(hist[i]-F)/F; /*\chi^2の計算*/
}
printf("chi^2=%f\n",e);
}
unsigned irnd(void) /*0-32767 の整数乱数*/
{
rndnum=(rndnum*109+1021)%32768;
return rndnum;
}
double rnd(void) /*0-1未満の実数乱数*/
{
return irnd()/32767.1;
}
Back to C Language

