生成正态分布随机数-C语言

        Box-Muller变换是一种常用的生成服从标准正态分布(均值为0,标准差为1)随机变量的方法。其原理基于极坐标的思想,将由均匀分布产生的随机数转换为标准正态分布的随机数对。

Box-Muller变换的算法如下:

  1. 从区间(0, 1)内均匀地生成两个独立的随机数,记作 U_1​ 和 U_2
  2. 计算变量:

    Z_0 = \sqrt{-2\ln(U_1)}*\cos(2\pi*U_2)

    Z_1 = \sqrt{-2\ln(U_1)}*\sin(2\pi*U_2)

  3. Z_0​ 和 Z_1 即为符合标准正态分布的独立随机变量。

        这里的 U_1U_2​ 是在 (0, 1)上的均匀分布随机数,Z_0​ 和 Z_1是由 Box-Muller 变换生成的符合标准正态分布的随机变量。

       当 U_1U_2独立且均匀分布在 (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)

### 如何使用C语言生成正态分布随机数 在C语言中,可以通过多种方法生成正态分布随机数。其中最常用的方法之一是 **Box-Muller 转换算法**,它通过两个独立的均匀分布随机数生成一对独立的标准正态分布随机数[^2]。 以下是基于 Box-Muller 方法的一个具体实现: #### 实现代码 ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> // 定义生成标准正态分布随机数的函数 double generate_normal(double mean, double stddev) { static int iset = 0; static double gset; double fac, rsq, v1, v2; if (iset == 0) { do { v1 = 2.0 * rand() / RAND_MAX - 1.0; // [-1, 1] v2 = 2.0 * rand() / RAND_MAX - 1.0; // [-1, 1] rsq = v1 * v1 + v2 * v2; } while (rsq >= 1.0 || rsq == 0); fac = sqrt(-2.0 * log(rsq) / rsq); gset = v1 * fac; iset = 1; return v2 * fac * stddev + mean; } else { iset = 0; return gset * stddev + mean; } } int main() { srand((unsigned) time(NULL)); // 初始化随机种子 double mean = 0.0; // 设置期望值 μ double stddev = 1.0; // 设置标准差 σ for (int i = 0; i < 10; i++) { printf("%.6f\n", generate_normal(mean, stddev)); } return 0; } ``` #### 代码说明 - `rand()` 函数用于生成随机数,范围为 `[0, RAND_MAX]`。 - 使用 `v1` 和 `v2` 表示二维平面上的一对随机向量分量,其模平方 (`rsq`) 需小于等于 1 才有效。 - 计算因子 `fac` 并应用 Box-Muller 公式完成转换。 - 返回的结果经过缩放和平移操作,使其具有指定的均值和方差[^3]。 --- 除了 Box-Muller 方法外,还可以采用其他技术如拒绝采样法(Rejection Sampling),这种方法的思想是在一个更大的矩形区域内随机抽样并剔除不符合条件的部分点[^5]。 无论哪种方式,都需要依赖高质量的基础随机数发生器以及精确的数学运算库支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值