迭代法求解线性方程组(C++实现)

2023-11-17

本系列是数值分析相关算法的文章,这次用迭代法求解线性方程组,不同于上次用高斯消元法之类的求解。迭代法对于稀疏矩阵方程组的运算,会大大提高。而如果用高斯相关的算法求解,会浪费大量资源计算无用的东西,所以有必要研究此算法。
本文章主要使用了3个算法,分别是雅可比迭代法、高斯-塞德尔迭代法、超松弛迭代法。每一个算法都比前一次的迭代次数少。下面贴代码!

#include <iostream>
#include<cmath>
using namespace std;
//数组的大小
const int n = 4;

//子程序,用来向量的无穷范数,该定义可以参看《数值分析》(第5版——清华大学出版社)P164页
template<class T>
T MAX(T a[n])
{
    T max = 0;
    for (int i = 0; i<n; i++)
    {
        if (fabs(a[i])>max)
            max = fabs(a[i]);
    }
    return max;
}
//求解线性方程组的雅可比迭代法
template<class T>
void Jacobi(T a[n][n], T b[n])
{
    int count = 0;
    T aaa;
    T bbb;
    int i, j;
    T  ccc;
    T xk[n] = { 0 };
    double x0[n];
    double xxx;
    bool ddd;
    //求解的过程,递归求解。
    do {
        count++;
        for (j = 0; j<n; j++)
            x0[j] = xk[j];

        for (i = 0; i<n; i++)
        {
            T sum = 0;
            for (j = 0; j<n; j++)
            {
                if (j == i)
                    continue;
                else
                    sum += a[i][j] * x0[j];
            }
            xk[i] = (b[i] - sum) / a[i][i];
    //      cout << "xk[" << i + 1 << "]=" << xk[i] << endl;
        }
        aaa = MAX(xk);                           //求出xk的无穷范数
    //  cout << aaa << endl;  
        bbb = MAX(x0);                           //求出x0的无穷范数
    //  cout << bbb << endl;
        ccc = fabs(bbb - aaa);                     //做差
    //  cout << ccc << endl;
        xxx = fabs(ccc - 0.000001);                       //与要满足的误差精度作比较,我设定的是迭代精度为0.000001
    //  cout << xxx << endl;
        if (xxx<0.000001)
            ddd = 0;
        else
            ddd = 1;
    } while (ddd);                           //判断是否在迭代精度外

    cout << "this is JACOBI method  " << endl;                    //输出最后结果
    for (i = 0; i<n; i++)
        cout << "x[" << i + 1 << "]= " << xk[i] << endl;
    cout << "recursive times:  " << count << endl;
}

//高斯-塞德尔迭代法
template<class T>
void Gausssin_Jacobi(T a[n][n], T b[n])
{
    int count = 0;
    T aaa;
    T bbb;
    int i, j;
    T  ccc;
    double xxx;
    bool ddd;
    T x0[n];
    T xk[n] = { 0 };
    //迭代计算过程
    do {
        count++;          //记录迭代次数
        //先复制数组,可以与后面计算后的迭代结果做差
        for (j = 0; j<n; j++)
            x0[j] = xk[j];
        //计算过程
        for (i = 0; i<n; i++)
        {
            T sum1 = 0;
            T sum2 = 0;
            for (j = 0; j<=i - 1; j++)
            {
                sum1 += a[i][j] * xk[j];
            }
            for (j = i + 1; j<n; j++)
                sum2 += a[i][j] * x0[j];

            xk[i] = (b[i] - sum1 - sum2) / a[i][i];
        //  cout << "this is the XK[" << i + 1 << "]=" << xk[i] << endl;
        }
        aaa = MAX(xk);                                         //求出xk的范数
    //  cout << "this is XK de fanshu" << aaa << endl;
        bbb = MAX(x0);                                         //求出x0的范数
    //  cout << "this is x0 de fanshu" << bbb << endl;
        ccc = fabs(bbb - aaa);                                 //范数之差
    //  cout << "cha zhi de daxiao" << ccc << endl;
        xxx = fabs(ccc - 0.000001);                           //范数之差与精度的比较
    //  cout << "this is panduan de daxiao" << xxx << endl << endl;
        if (xxx<0.000001)
            ddd = 0;
        else
            ddd = 1;
    } while (ddd);                                 

    //输出结果
    cout << "this is Gausssin_Jacobi method  " << endl;
    for (i = 0; i<n; i++)
        cout << "x[" << i + 1 << "]= " << xk[i] << endl;
     cout << "recursive times:" << count << endl;
}


//超松弛迭代法(successive over relaxation method)(SOR方法)
template<class T>
void SOR(T a[n][n], T b[n],double w)
{
    int count = 0;
    T aaa;
    T bbb;
    int i, j;
    T  ccc;
    double xxx;
    bool ddd;
    T x0[n];
    T xk[n] = { 0 };
    T xk_[n] = { 0 };
    //迭代计算过程
    do {
        count++;               //记录迭代次数
        //先复制数组,可以与后面计算后的迭代结果做差
        for (j = 0; j<n; j++)
            x0[j] = xk[j];
        //计算过程
        for (i = 0; i<n; i++)
        {
            T sum1 = 0;
            T sum2 = 0;
            for (j = 0; j <= i - 1; j++)
            {
                sum1 += a[i][j] * xk[j];
            }
            for (j = i+1 ; j<n; j++)
                sum2 += a[i][j] * x0[j];

            xk_[i] = (b[i] - sum1 - sum2) / a[i][i];
            xk[i] = (1 - w)*x0[i] + w*xk_[i];
  //    cout << "this is the XK[" << i + 1 << "]=" << xk[i] << endl;
        }
        aaa = MAX(xk);                                         //求出xk的范数
//      cout << "this is XK de fanshu" << aaa << endl;
        bbb = MAX(x0);                                         //求出x0的范数
   //   cout << "this is x0 de fanshu" << bbb << endl;
        ccc = fabs(bbb - aaa);                                 //范数之差
   //   cout << "cha zhi de daxiao" << ccc << endl;
        xxx = fabs(ccc - 0.000001);                           //范数之差与精度的比较
  //    cout << "this is panduan de daxiao" << xxx << endl << endl;
        if (xxx<0.000001)
            ddd = 0;
        else
            ddd = 1;
    } while (ddd);

    //输出结果
    cout << "this is successive over relaxation  method  " << endl;
    for (i = 0; i<n; i++)
        cout << "x[" << i + 1 << "]= " << xk[i] << endl;
    cout << "recursive times: "<< count << endl;
    cout << endl;
}

下面是测试和输出:

int main()
{
    double a[4][4] = { -4,1,1,1,1,-4,1,1,1,1,-4,1,1,1,1,-4 };
    double x[4] = { 1,1,1,1 };
    Jacobi(a, x);
    Gausssin_Jacobi(a, x);
    cout<<endl;

    SOR(a, x,1.3);
    return 0;
}                                                                                                                                    this is JACOBI method
x[1]= -0.999994
x[2]= -0.999994
x[3]= -0.999994
x[4]= -0.999994
recursive times:  42
this is Gausssin_Jacobi method
x[1]= -0.999997
x[2]= -0.999997
x[3]= -0.999997
x[4]= -0.999998
recursive times:23

this is successive over relaxation  method
x[1]= -1
x[2]= -0.999999
x[3]= -1
x[4]= -1
recursive times: 12

对于输出,可以看到,SOR方法满足同样精度的话,迭代次数更少。在从与精确解的精度比较,显然SOR方法的精度更高,但是SOR的松弛因子的选取是个很大的问题,选好了对于计算有很大的便利。这是该算法性能的关键。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

迭代法求解线性方程组(C++实现) 的相关文章

  • 软件质量测试雨课堂习题

    目录 第一章 软件测试基础 第二章 软件测试策略 第五章 软件测试的过程管理 第六章 软件测试的度量 第七章 软件测试技术 第九章 第三方测试 第一章 软件测试基础 1 软件测试目的是什么 ABC A 修正软件错误和缺陷提高软件质量 B 发
  • 从零开始的自动化测试框架——Web篇01

    Selenium 谈到web自动化 逃不开的一定会是Selenium 这是最为主流 也是最广为人知的一项web自动化产物 但目前业内web自动化其实主要分为以下方向 Selenium 核心主流自动化技术 功能齐全 一般是搭配webdrive

随机推荐

  • vue3中引入省市区地区选择element-china-area-data及页面回显

    安装element china area data npm i element china area data 引入 import regionData CodeToText TextToCode from element china ar
  • 【echarts报错】: ‘normal‘ hierarchy in itemStyle has been removed since 4.0.

    文章目录 报错 分析 解决 报错 charts5 js 7169 ECharts DEPRECATED normal hierarchy in itemStyle has been removed since 4 0 All style p
  • Mac安装sshpass同时解决Calling Non-checksummed download of sshpass formula file from an arbitrary URL报错

    可以直接使用 brew install https raw githubusercontent com kadwanev bigboybrew master Library Formula sshpass rb 但是会报错 Error Ca
  • 软件测试员一定需要懂编程代码吗?

    软件测试人员需要懂代码吗 如果软件测试人员会代码 那还有软件开发人员的事吗 既能测试又能敲代码的人是不是很牛 不管是外行人还是内行人 对一份与自己无关的职业的认识往往缺乏基本的认知 比如今天要说的软件测试 很多人都会对软件测试这个岗位存在一
  • 回顾:网络编程(待排版,知识点看情况补充

    一 CS模型 整个流程 服务器启动后 首先创建一个 或多个 监听socket 并调用bind函数将其绑定到服务器感兴趣的端口上 然后调用listen函数等待客户连接 服务器稳定运行之后 客户端就可以调用connect函数向服务器发起连接 由
  • Java String类型数据转为Byte数据

    方式一 我们可以直接通过Byte decode 方式直接转化内 String str 1 Byte decode Byte decode str System out println decode 方式二 首先我们可以先将String转为i
  • 区块链优秀gitbook资料

    docker 从入门到实践 https yeasy gitbooks io docker practice content image list html go 语言圣经 https docs hacknode org gopl zh ch
  • 双向链表(数据结构)(C语言)

    目录 概念 带头双向循环链表的实现 前情提示 双向链表的结构体定义 双向链表的初始化 关于无头单向非循环链表无需初始化函数 顺序表 带头双向循环链表需要的思考 双向链表在pos位置之前插入x 双向链表的打印 双链表删除pos位置的结点 双向
  • 学习总结4.1 Linux文件权限修改

    Linux系统中的每个文件都有访问许可权限 文件的访问权限分为只读 只写和可执行三种 只读权限表示只允许读其内容 而禁止对其做任何的更改操作 只写权限表示允许修改文件的内容 可执行权限表示允许将该文件作为一个程序执行 每一文件的访问权限都有
  • c/c++笔试面试题_6

    几个简单的c 面试题 2006 10 14 14 50 今天偶然看见这几个面试题 很有感触 想起一年前自己的求职经历 1 引言 本文的写作目的并不在于提供C C 程序员求职面试指导 而旨在从技术上分析面试题的内涵 文中的大多数面试题来自各大
  • 谷歌浏览器Google Chrome离线版(持续更新中)

    谷歌浏览器官方正式版采用自主研发Chromium内核 它是全球受欢迎的谷歌浏览器电脑版 追求速度 隐私安全的网络浏览器 而Google Chrome浏览器离线版更可以在无网络的情况下安装 一 在线版和离线版区别 在线版 即下载官方下载的一个
  • 服务链路追踪(Spring Cloud Sleuth)

    sleuth 英 slu 美 slu n 足迹 警犬 侦探vi 做侦探 微服务架构是一个分布式架构 它按业务划分服务单元 一个分布式系统往往有很多个服务单元 由于服务单元数量众多 业务的复杂性 如果出现了错误和异常 很难去定位 主要体现在
  • java中使用spark如何将column多列合为一列

    接下来介绍几种使用spark将DataFrame中一行的多列合并到一列中 并且该列以不同的类型展示保存 1 建立dataset 自己需要连接的mongo库 private static String datasource 自己需要连接的mo
  • 第十课.图片风格迁移和GAN

    目录 Neural Style Transfer Neural Style Transfer原理 准备工作 定义模型并加载预训练的模型参数 训练target以及结果可视化 生成对抗网络GAN GAN原理 GAN生成Mnist 准备工作 模型
  • 博客系统文章的数据库存储方式

    在通常的博客系统中 我们发表文章的时候 在数据库中存储的一般不仅仅是文章的文字 还包括文章的样式 而且很多时候都是所见即所得的效果 这就要求我们以html 文字这样存进数据库中 通过查找资料 可以用专门的文字编辑器可以实现 使用方法如下 F
  • 系统架构设计师之网络安全-各个层次的网络安全保障

    系统架构设计师之网络安全 各个层次的网络安全保障
  • Map集合知识点整理

    目录 一 Map集合概述 1 特点 2 Map集合的基本功能 二 实现类HashMap集合 1 概述 2 常用方法总结 3 HashMap的底层实现 4 LinkedHashMap 5 TreeMap 三 Map集合的遍历方式 四 案例演示
  • 文献管理软件--zotero基本使用

    文章目录 一 下载与安装 1 下载插件 以火狐浏览器为例 2 注册账户 3 下载桌面版 二 文献导入 1 新建文件 2 导入文献 3 本地导入 4 支持批量下载 三 文献管理 1 添加标签 2 添加子目录 3 添加笔记 四 添加插件 五 数
  • MyBatis的逆向工程

    MyBatis的逆向工程 正向工程 先创建Java实体类 由框架负责根据实体类生成数据库表 Hibernate是支持正向工程的 逆向工程 先创建数据库表 由框架负责根据数据库表 反向生成如下资源 Java实体类 Mapper接口 Mappe
  • 迭代法求解线性方程组(C++实现)

    本系列是数值分析相关算法的文章 这次用迭代法求解线性方程组 不同于上次用高斯消元法之类的求解 迭代法对于稀疏矩阵方程组的运算 会大大提高 而如果用高斯相关的算法求解 会浪费大量资源计算无用的东西 所以有必要研究此算法 本文章主要使用了3个算