跳转至

C 语言复合数列递推

一段简短的 C 代码,模拟两个相互影响的序列递推过程。初始值各为 100,每轮按固定比例从对方序列中吸收一部分,迭代 100 轮后收敛至稳定比例。

原始代码

#include <stdio.h>

int main()
{
    int len = 100;
    float a[len], b[len];
    a[0] = 100, b[0] = 100;
    for (int i = 1; i < len; i++)
    {
        a[i] = 0.9 * a[i - 1] + 0.15 * b[i - 1];
        b[i] = 0.85 * b[i - 1] + 0.1 * a[i - 1];
        printf("%lf %lf\n", a[i], b[i]);
    }
    return 0;
}

问题

变长数组

int len = 100; float a[len]; 用的是 C99 的变长数组(VLA)。MSVC 不支持 VLA,代码在 Visual Studio 下无法编译。应改用 #defineconst

float 精度

连续 100 次浮点迭代,float 的 6~7 位有效数字在后半程会积累误差。用 double 更可靠。

仅输出数值,缺少分析

程序忠实地算出了每一轮的值,但没有说明这个系统在做什么、最终会收敛到哪里。


数学分析

将递推写成矩阵形式:

\[ \begin{bmatrix} a_i \\ b_i \end{bmatrix} = \begin{bmatrix} 0.9 & 0.15 \\ 0.1 & 0.85 \end{bmatrix} \begin{bmatrix} a_{i-1} \\ b_{i-1} \end{bmatrix} \]

提取两个信息:

总量守恒。每轮 a 流失 10% 到 b、b 流失 15% 到 a,但恰好:

\[ a_i + b_i = (0.9+0.1)a_{i-1} + (0.15+0.85)b_{i-1} = a_{i-1} + b_{i-1} = 200 \]

总量始终锁定在 200。

特征值与稳态。转移矩阵的特征方程为:

\[ \lambda^2 - 1.75\lambda + 0.75 = 0 \]

解得 \(\lambda_1 = 1.0\)\(\lambda_2 = 0.75\)。对应 \(\lambda_1=1\) 的特征向量满足 \(a = 1.5b\),即 a 与 b 的比例收敛至 3:2。结合总量 200,稳态值:

\[ a_{\infty} = \frac{3}{5} \times 200 = 120,\qquad b_{\infty} = \frac{2}{5} \times 200 = 80 \]

修正后代码

#include <stdio.h>

#define LEN 100                                 // 修正:用宏替代 VLA

int main()
{
    double a[LEN], b[LEN];                      // 修正:double 替代 float
    a[0] = 100, b[0] = 100;

    printf("轮次    a          b\n");
    for (int i = 1; i < LEN; i++)
    {
        a[i] = 0.9 * a[i - 1] + 0.15 * b[i - 1];
        b[i] = 0.85 * b[i - 1] + 0.1 * a[i - 1];
        printf("%3d  %8.4lf  %8.4lf\n", i, a[i], b[i]);  // 修正:格式控制
    }

    printf("\n理论稳态: a = 120.0, b = 80.0\n");
    return 0;
}

运行前 10 轮输出:

轮次    a          b
  1    105.0000   95.0000
  2    108.7500   91.2500
  3    111.5625   88.4375
  4    113.6719   86.3281
  5    115.2539   84.7461
  6    116.4404   83.5596
  7    117.3303   82.6697
  8    117.9977   82.0023
  9    118.4983   81.5017
 10    118.8737   81.1263

a 从 100 单调上升趋近 120,b 从 100 单调下降趋近 80。到第 40 轮左右,两者距离稳态已不足 0.01。