规格化就是把随机变量的取值限制在[0,1)之间。
尝试过从双精的标准出发得到随机数,但那样很难保证其等概率性,于是还是从rand()的标准出发吧。
ANSI C给出了标准的随机变量计算方法和函数。其算法可以查相关资料,现只给出函数原型:
int rand(void);
返回值为int型,在WIN32里是4个字节,但实际上有用部分只有前15bit,生成的随机数是一个0~0x7FFF(十进制32767)的随机正整数。这里假设由标准算法生成的随机数的这15个bit是等概率得到0或1的,那么就用它‘拼’成更高一些位数的随机数,于是给出下面的算法:
double drand(void)
{
return (double)(
rand()<<15 | rand()
) /
(double)0x40000000;
}
rand()<<15 | rand() 将拼成一个30bit的随机整数,取值0~3FFFFFFF,于是相除之后将得到大于等于0小于1的小数。
使用
得到任意范围[a,b)内的随机浮点数:
double i=a+drand()*(b-a);
float j=a+(float)(drand()*(b-a));
得到任意范围[a,b]内的随机整数:
int i=a+(int)(drand()*(1+b-a));
测试
接合前面的算法,给出如下的测试用例:
double frand(double (*p)(double),double h)
{
double x=drand(),y=drand()*h;
if(y<p(x))return x;
return frand(p,h);
}
double testPfunction(double x)
{
if(x<0.333333)return 0.5;
if(x<0.666667)return 1;
return 1.5;
}
void main(void)
{
int n,v[100]={0};
cin>>n;
for(int i=0;i<n;++i)
v[(int)(frand(testPfunction,2)*100)]++;
for(int j=0;j<100;++j)
cout<<v[j]<<endl;
}
测试结果
10000
44
60
54
54
66
53
40
49
41
49
51
46
64
49
46
45
53
64
59
55
55
57
47
52
58
53
45
60
43
57
38
50
44
82
75
87
109
104
97
90
103
95
100
101
104
111
86
106
97
104
83
100
102
109
103
99
97
115
109
97
98
94
121
97
112
106
99
148
154
153
172
134
163
145
145
149
137
124
156
144
154
125
158
138
138
136
162
149
134
171
159
153
159
161
134
155
135
134
163
165
评论