[计算机数值分析]高斯-塞德尔迭代公式解线性方程组

Spring-_-Bear 的 CSDN 博客导航

雅可比迭代公式 的基础上,设已得到近似值( x 1 ( k ) , x 2 ( k ) , x 3 ( k ) x_{1}^{(k)}, x_{2}^{(k)}, x_{3}^{(k)} x1(k),x2(k),x3(k)),则由方程 (1)1

{ x 1 = 0.1 x 2 + 0.2 x 3 + 0.72 x 2 = 0.1 x 1 + 0.2 x 3 + 0.83 x 3 = 0.2 x 1 + 0.2 x 2 + 0.84 (1) \begin{cases} x_{1}=0.1x_{2}+0.2x_{3}+0.72\\ x_{2}=0.1x_{1}+0.2x_{3}+0.83\\ x_{3}=0.2x_{1}+0.2x_{2}+0.84\\ \end{cases}\tag1 x1=0.1x2+0.2x3+0.72x2=0.1x1+0.2x3+0.83x3=0.2x1+0.2x2+0.84(1)

x 1 ( k + 1 ) = 0.1 x 2 ( k ) + 0.2 x 3 ( k ) + 0.72 x_{1}^{(k+1)}=0.1x_{2}^{(k)}+0.2x_{3}^{(k)}+0.72 x1(k+1)=0.1x2(k)+0.2x3(k)+0.72

对于收敛的迭代过程,所求出的 “新值” x 1 ( k + 1 ) x_{1}^{(k+1)} x1(k+1) 常比 “老值” x 1 ( k ) x_{1}^{(k)} x1(k) 更准确些,因此可用它替代老值 x 1 ( k ) x_{1}^{(k)} x1(k) 作进一步的计算,将 x 1 ( k + 1 ) x_{1}^{(k+1)} x1(k+1) x 3 ( k ) x_{3}^{(k)} x3(k) 一起代入 (1)2

x 2 ( k + 1 ) = 0.1 x 1 ( k + 1 ) + 0.2 x 3 ( k ) + 0.83 x_{2}^{(k+1)}=0.1x_{1}^{(k+1)}+0.2x_{3}^{(k)}+0.83 x2(k+1)=0.1x1(k+1)+0.2x3(k)+0.83

处于同样得考虑,我们再用新值 x 2 ( k + 1 ) x_{2}^{(k+1)} x2(k+1) 替代老值 x 2 ( 1 ) x_{2}^{(1)} x2(1),由方程 (1)3

x 3 ( k + 1 ) = 0.2 x 1 ( k + 1 ) + 0.2 x 2 ( k + 1 ) + 0.84 x_{3}^{(k+1)}=0.2x_{1}^{(k+1)}+0.2x_{2}^{(k+1)}+0.84 x3(k+1)=0.2x1(k+1)+0.2x2(k+1)+0.84

这种充分利用新值建立起来的迭代公式称作解方程组(1)的高斯 - 塞德尔公式,如(2)所示。

{ x 1 ( k + 1 ) = 0.1 x 2 ( k ) + 0.2 x 3 ( k ) + 0.72 x 2 ( k + 1 ) = 0.1 x 1 ( k + 1 ) + 0.2 x 3 ( k ) + 0.83 x 3 ( k + 1 ) = 0.2 x 1 ( k + 1 ) + 0.2 x 2 ( k + 1 ) + 0.84 (2) \begin{cases} x_{1}^{(k+1)}=0.1x_{2}^{(k)}+0.2x_{3}^{(k)}+0.72\\ x_{2}^{(k+1)}=0.1x_{1}^{(k+1)}+0.2x_{3}^{(k)}+0.83\\ x_{3}^{(k+1)}=0.2x_{1}^{(k+1)}+0.2x_{2}^{(k+1)}+0.84\\ \end{cases}\tag2 x1(k+1)=0.1x2(k)+0.2x3(k)+0.72x2(k+1)=0.1x1(k+1)+0.2x3(k)+0.83x3(k+1)=0.2x1(k+1)+0.2x2(k+1)+0.84(2)

仍取初值 x 1 ( 0 ) = x 2 ( 0 ) = x 3 ( 0 ) = 0 x_{1}^{(0)}=x_{2}^{(0)}=x_{3}^{(0)}=0 x1(0)=x2(0)=x3(0)=0,按式(2)的计算结果如下表,与 雅可比迭代公式 相比效果更好。

kx1(k)x2(k)x3(k)
00.000000.000000.00000
10.720000.902001.16440
21.043081.167191.28205
31.093131.195721.29777
41.099131.199471.29972
51.099891.199931.29997
61.099991.199991.30000

运行示例:

在这里插入图片描述

程序源码:

#include <iostream>
#include <iomanip>

#define MAX 10

using namespace std;

int main(void)
{
    int row;
    cout << "请输入增广矩阵行数:";
    cin >> row;

    int col;
    cout << "请输入增广矩阵列数:";
    cin >> col;

    double a[MAX][MAX];
    for (int i = 1; i <= row; i++)
    {
        cout << "请输入增广矩阵第 " << i << " 行的元素:";
        for (int j = 1; j <= col; j++)
        {
            cin >> a[i][j];
        }
    }

    // 对增广矩阵元素进行处理化简
    for (int i = 1; i <= row; i++)
    {
        for (int j = 1; j <= col; j++)
        {
            if (i != j && j != col)
            {
                // 非行列坐标相等的元素除以负行列坐标相等的元素
                a[i][j] /= -a[i][i];
            }
            if (j == col)
            {
                // 常数项除以行列相等的元素
                a[i][j] /= a[i][i];
            }
        }
    }

    // 将矩阵主对角线上的元素赋值为 0
    for (int i = 1; i <= row; i++)
    {
        a[i][i] = 0;
    }

    double b[MAX];
    cout << "请输入迭代初值:";
    for (int i = 1; i < col; i++)
    {
        cin >> b[i];
    }

    int N;
    cout << "请输入最大迭代次数:";
    cin >> N;

    double accuracy;
    cout << "请输入精度:";
    cin >> accuracy;

    double error = 0;
    for (int i = 1; i <= N; i++)
    {
        cout << "第 " << i << " 次迭代:";

        // 用 count 控制迭代值按每行 col-1 个输出,即自变量个数输出
        int count = 1;
        // 每一次迭代 (i),求取每一行的行列坐标相等的值即 a[j][j]
        for (int j = 1; j <= row; j++)
        {
            // j 循环 col 次,求得 a[j][j]
            double item;
            for (int k = 1; k <= col; k++)
            {
                if (j == k)
                {
                    continue;
                }

                if (k != col)
                {
                    // 如果 j 不等于 k 且不等于常数项的下标,则每一项等于系数与对应迭代初值的乘积
                    item = a[j][k] * b[k];
                }
                else
                {
                    // j=col 即常数项下标时,直接加上常数项,不对常数项处理
                    item = a[j][col];
                }

                // 累加 item,求得 a[1][1], a[2][2]......
                a[j][j] += item;
            }
            // 输出 a[1][1], a[2][2]......
            cout << "\t\t" << a[j][j] << "\t\t";

            // 相邻两次迭代结果的偏差
            error = abs(a[count][count] - b[count]);
            // 更新 b[] 里的值为本次迭代结束的值
            b[count] = a[count][count];
            // 赋 a[1][1], a[2][2]......值为 0,避免拥有初值影响下一次迭代结果
            a[count][count] = 0;

            if (count % (col - 1) == 0)
                cout << endl;
            count++;
        }

        // 解符合精度要求,直接结束迭代过程
        if (error <= accuracy)
        {
            break;
        }

        if (i > N)
        {
            cout << "达到允许的最大迭代次数,未找到符合精度要求的根!" << endl;
            break;
        }
    }

    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春天熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值