2-2、线性代数方程组的求解

内容来自王晓华老师

这块内容有点硬核,先做了解,主要学习如何使用迭代解决问题的步骤

 

两种常用的迭代法求解方程组,分别是雅可比迭代法(Jacobi)和高斯—赛德尔迭代法(Gauss—Seidel)

 

完整的雅可比迭代算法

const double PRECISION = 0.000000001;
const int VEC_N = 16;  //实际方程组的个数 n 必须小于VEC_N

void jacobi_eqn(double a[][VEC_N], double b[], int n, double x[])
{
    double xt[VEC_N];
    double max_diff = 0.0;

    do
    {
        for (int i = 0; i < n; i++)
        {
            double sum = 0.0;
            for (int k = 0; k < n; k++)
            {
                if (i != k)  //对角线元素不计算
                {
                    sum += a[i][k] * x[k];
                }
            }
            xt[i] = (b[i] - sum) / a[i][i];   //根据关系计算 xi 的新值
        }

        max_diff = calc_max_diff(xt, x, n);

        for (int j = 0; j < n; j++)
        {
            x[j] = xt[j]; //更新 x,准备下一次迭代
        }
    } while (max_diff > PRECISION);
}

 

高斯-赛德尔迭代法
雅可比迭代法每次迭代计算时,将上一次的迭代变量整体带入到迭代关系式中,计算新的迭代变量值,也就是所谓的整体迭代。在迭代收敛的前提下,如果迭代变量中的每个分量 x 在计算出新的迭代值后,直接带入迭代,参与其他迭代分量的计算,则能显著地提高迭代效果,这种改进的方法就是高斯-赛德尔迭代法。
从算法实现的角度理解,这种改进思想就是每计算出一个迭代分量的新迭代值,就立即让它参与到其他迭代分量的计算中,其迭代关系可以理解为:

const double PRECISION = 0.000000001;
const int VEC_N = 16;  //实际方程组的个数 n 必须小于 VEC_N

void gauss_seidel_eqn(double a[][VEC_N], double b[], int n, double x[])
{
    double max_diff = 0.0;

    do
    {
        max_diff = 0.0;
        for (int i = 0; i < n; i++)
        {
            double sum = 0.0;
            for (int k = 0; k < n; k++)
            {
                if (i != k)  //对角线元素不计算
                {
                    sum += a[i][k] * x[k];
                }
            }
            double xt = (b[i] - sum) / a[i][i];   //根据关系计算 xi 的新值
            if (std::fabs(xt - x[i]) > max_diff) //max_diff 只保留差值最大的
            {
                max_diff = std::fabs(xt - x[i]);
            }
            x[i] = xt;
        }
    } while (max_diff > PRECISION);
}

 

posted @ 2019-05-31 18:25  orxx  阅读(1703)  评论(0编辑  收藏  举报