Box-Muller变换是一种常用的生成服从标准正态分布(均值为0,标准差为1)随机变量的方法。其原理基于极坐标的思想,将由均匀分布产生的随机数转换为标准正态分布的随机数对。
Box-Muller变换的算法如下:
- 从区间(0, 1)内均匀地生成两个独立的随机数,记作
和
。
- 计算变量:
和
即为符合标准正态分布的独立随机变量。
这里的 和
是在 (0, 1)上的均匀分布随机数,
和
是由 Box-Muller 变换生成的符合标准正态分布的随机变量。
当 和
独立且均匀分布在 (0, 1)区间内时,通过对它们进行适当的函数变换,可以得到满足高斯分布的随机变量。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
double generate_normal(double mean, double stddev) {
static double z1, z2;
static int generate;
generate = !generate;
if (!generate)
return z2 * stddev + mean;
double u1, u2;
do {
u1 = rand() * (1.0 / RAND_MAX);
u2 = rand() * (1.0 / RAND_MAX);
} while (u1 <= 1e-7);
z1 = sqrt(-2.0 * log(u1)) * cos(2 * M_PI * u2);
z2 = sqrt(-2.0 * log(u1)) * sin(2 * M_PI * u2);
return z1 * stddev + mean;
}
int main() {
srand(time(NULL));
double mean = 0.0; // 指定均值
double stddev = 1.0; // 指定标准差
int i;
for (i = 0; i < 100; i++) {
printf("%f ", generate_normal(mean, stddev));
if(i%10 == 0)
printf("\n ");
}
return 0;
}
上述代码最后测试生成10个均值为0,标准差为1的正态分布随机数,下面是一次生成的结果。
-0.304427 -1.709132 -0.637457 -0.115340 0.391374 0.818611 -0.757250 2.521892 -0.796964 0.969829
0.356248 -1.553272 -1.190531 -0.486877 0.487952 -0.648820 1.110085 0.060086 0.776557 1.795561
0.387308 0.144394 -1.102004 0.396821 -0.202300 -0.882435 0.634188 1.120585 1.737933 -0.066684
0.392063 1.358983 1.178477 1.399557 0.334565 -0.027261 0.032823 0.921120 -1.203685 0.995437
-0.327912 0.741170 -0.195522 0.012784 -0.331244 1.375677 2.280650 -0.319563 1.460647 0.298711
-1.700978 -0.310468 1.690571 -1.187290 1.389037 -1.114818 0.238236 -0.464428 0.815323 -0.009537
-1.882095 0.192120 0.096966 -0.133729 -0.918820 -0.852759 -0.218966 0.010652 1.551117 -0.162994
0.450467 -0.797384 2.906325 -0.493410 -1.435679 -0.931503 -0.295340 0.043493 0.336999 0.749057
2.829080 -0.646718 0.098094 -0.683147 -0.684769 0.886755 -0.737217 1.291919 -0.583261 -1.437409
1.076235 -0.399591 0.489981 0.586680 0.259332 0.332059 -2.030044 1.635369 -0.983929 -0.743155
原理详细推导参考:Box-Muller变换原理详解 - 知乎 (zhihu.com)