计算方法实验四 解线性方程组的间接方法

【实验性质】

综合性实验。

【实验目的】

掌握迭代法求解线性方程组。

【实验内容】

应用雅可比迭代法和Gauss-Sediel迭代法求解下方程组:

【理论基础】

线性方程组的数值解法分直接算法和迭代算法。迭代法将方程组的求解转化为构造一个向量序列,如果该向量序列存在极限,其极限就是方程组的解。

迭代法程序简单,但有时工作量较大,在有限步内,得不到精确解,适宜系数矩阵阶数较高的问题。

构造关于解向量的迭代序列,的常见方法有Jacobi迭代和Gauss-Seidel加速迭代。

设:

统一的迭代公式为:

−1

对于雅可比迭代,矩阵;对于高斯-赛德尔迭代,G = −(𝐷+L) 𝑈,f =(𝐷+L)−1𝑏。

实际的计算与编程应尽量避免矩阵求逆、矩阵相乘等运算,而使用如下公式:

【实验过程】

取三个不同初值,分别用雅可比法和高斯-塞得尔法求解,用表格记载求解过程,并分析迭代初值、迭代公式对迭代的影响。

附表:

|---|----|-----|------|-----|------|
| || 雅可比法 || 高斯-塞得尔法 ||
| | 初值 | 近似根 | 迭代次数 | 近似根 | 迭代次数 |
| 1 | | | | | |
| 2 | | | | | |
| 3 | | | | | |

代码:

主函数:

//实验四

#include <iostream>

#include <windows.h>

#include "colvector.h"

#include "matrix.h"

#include <windows.h>

#include "linearequations.h"

using namespace std;

int main()

{

double a1[]={8,7,0,0,6,12,5,0,0,4,9,3,0,0,1,2};

double b1[]={0,-2,8,6};

double x1[]={0,0,0,0};

double e=0.0001;

int flag=1,max=100;

Matrix A(4,4);

ColVector b(4),x(4),x0(4);

A.initMatrix(a1);

b.initMatrix(b1);

x0.initMatrix(x1);

LinearEquations obj;

obj.JacobiIterativeMethod(A,b,e,x0,max,flag,x);

cout<<x<<endl;

return 0;

}

头文件:

复制代码
#ifndef LINEAREQUATIONS_H
复制代码
#define LINEAREQUATIONS_H
复制代码
#include "matrix.h"
复制代码
#include "colvector.h"
复制代码
#include  <math.h>
复制代码
class LinearEquations
复制代码
{
复制代码
public:
复制代码
    void GaussElimin(Matrix A,ColVector b,int &flag,ColVector &x);
复制代码
    void colPivotGaussElimin(Matrix A,ColVector b,int &flag,ColVector &x);
复制代码
    void LUDecomposition(Matrix &mat,int &flag,Matrix &L,Matrix &U,int type=1);
复制代码
    void TrigDecompositionMethod(Matrix &A,ColVector &b,int &flag,ColVector &x,int type=1);
复制代码
    void Catchup(ColVector&a,ColVector &b,ColVector &c,ColVector &f,int &flag,ColVector &x,int type=1);
复制代码
    LinearEquations();
复制代码
    //雅可比迭代
复制代码
    void JacobiIterativeMethod(Matrix &A,ColVector &b,double e,ColVector &x0,int MAX, int &flag,ColVector &x);
复制代码
    //高斯-赛德尔迭代
复制代码
    void Gauss_SeidelIterativeMethod(Matrix &A,ColVector &b,double e,ColVector &x0,int MAX, int &flag,ColVector &x);
复制代码
复制代码
};
复制代码
#endif // LINEAREQUATIONS_H
复制代码

源文件:

#include "linearequations.h"

LinearEquations::LinearEquations()

{

}

void LinearEquations::GaussElimin(Matrix A,ColVector b,int &flag,ColVector &x)

{

flag=1;

int n=A.getRowSize();

if(n!=A.getColSize() || n!=b.getRowSize())

{

flag =0;

return;

}

cout<<"初始曾广矩阵"<<Matrix::merge(A,b)<<endl;

for(int k=1;k<=n-1;k++)

{

for(int i=k+1;i<=n;i++)

{

if(A(k,k)==0)

{

flag =0;

return;

}

double m=A(i,k)/A(k,k);

for(int j=1;j<=n;j++)

{

A(i,j)=A(i,j)-m*A(k,j);

}

b[i]=b[i]-m*b[k];

}

cout<<"第"<<k<<"次消元"<<Matrix::merge(A,b)<<endl;

}

cout<<"解 x"<<endl;

x=ColVector(n);

if(A(n,n)==0)

{

flag=0;

return;

}

x[n]=b[n]/A(n,n);

cout<<x<<endl;

for(int i=n-1;i>=1;i--)

{

double sum=0;

for(int j=i+1;j<=n;j++)

{

sum+=A(i,j)*x[j];

}

x[i]=(b[i]-sum)/A(i,i);

cout<<"解 x"<<endl;

cout<<x<<endl;

}

}

void LinearEquations::colPivotGaussElimin(Matrix A,ColVector b,int &flag,ColVector &x)

{

flag=1;

int n=A.getRowSize();

if(n!=A.getColSize() || n!=b.getRowSize())

{

flag =0;

return;

}

cout<<"初始曾广矩阵"<<Matrix::merge(A,b)<<endl;

for(int k=1;k<=n-1;k++)

{

double max=fabs(A(k,k));

int p=k;

for(int w=k+1;w<=n;w++)

{

if(max< fabs(A(w,k))){

max=fabs(A(w,k));

p=w;

}

}

if(max==0){

flag=0;

return;

}

if(p!=k){

double temp=0;

for(int s=1;s<=n;s++)

{

temp =A(k,s);

A(k,s)=A(p,s);

A(p,s)=temp;

}

temp=b[k];

b[k]=b[p];

b[p]=temp;

}

for(int i=k+1;i<=n;i++)

{

if(A(k,k)==0)

{

flag =0;

return;

}

double m=A(i,k)/A(k,k);

for(int j=1;j<=n;j++)

{

A(i,j)=A(i,j)-m*A(k,j);

}

b[i]=b[i]-m*b[k];

}

cout<<"第"<<k<<"次消元"<<Matrix::merge(A,b)<<endl;

}

cout<<"解 x"<<endl;

x=ColVector(n);

if(A(n,n)==0)

{

flag=0;

return;

}

x[n]=b[n]/A(n,n);

cout<<x<<endl;

for(int i=n-1;i>=1;i--)

{

double sum=0;

for(int j=i+1;j<=n;j++)

{

sum+=A(i,j)*x[j];

}

x[i]=(b[i]-sum)/A(i,i);

cout<<"解 x"<<endl;

cout<<x<<endl;

}

}

void LinearEquations::LUDecomposition(Matrix &mat,int &flag,Matrix &L,Matrix &U,int type)

{

flag=0;

int n=mat.getRowSize();

if(n!=mat.getColSize()||type<1||type>2){

flag=-1;

return;

}

L=Matrix(n,n);

U=Matrix(n,n);

switch(type){

case 1:

for(int i=1;i<+n;i++){

U(1,i)=mat(1,i);

}

for(int i=1;i<=n;i++){

L(i,1)=mat(i,1)/U(1,1);

}

for(int k=2;k<=n;k++)

{

for(int j=k;j<=n;j++){

double sum=0;

for(int r=1;r<=k-1;r++){

sum+=L(k,r)*U(r,j);

}

U(k,j)=mat(k,j)-sum;

}

for(int i=k;i<=n;i++){

double sum=0;

for(int r=1;r<=k-1;r++){

sum+=L(i,r)*U(r,k);

}

L(i,k)=(mat(i,k)-sum)/U(k,k);

}

}

break;

case 2:

for(int k=1;k<=n;k++)

{

for(int j=k;j<=n;j++)

{

double sum=0;

if(k>1){

for(int r=1;r<=k-1;r++){

sum+=L(j,r)*U(r,k);

}

}

L(j,k)=mat(j,k)-sum;

}

for(int j=k;j<=n;j++)

{

if(L(k,k)==0){

flag=0;

return ;

}

double sum=0;

if(k>1)

{

for(int r=1;r<=k-1;r++){

sum+=L(k,r)+U(r,j);

}

}

U(k,j)=(mat(k,j)-sum)/L(k,k);

}

}

break;

}

}

void LinearEquations::TrigDecompositionMethod(Matrix &A,ColVector &b,int &flag,ColVector &x,int type)

{

flag =1;

int n=A.getRowSize();

if(n!=A.getColSize()||n!=b.getRowSize()||type<1||type>2)

{

flag=0;

return;

}

Matrix L,U;

ColVector y(n);

x=ColVector(n);

switch(type){

case 1:

LUDecomposition(A,flag,L,U);

if(flag== -1)

{

return;

}

y[1]=b[1];

for(int i=2;i<=n;i++)

{

double sum=0;

for(int k=1;k<=i-1;k++)

{

sum+=L(i,k)*y[k];

}

y[i]=b[i]-sum;

}

cout<<"y="<<y<<endl;

if(U(n,n)==0)

{

flag=0;

return;

}

x[n]=y[n]/U(n,n);

for(int i=n-1;i>=1;i--)

{

if(U(i,i)==0){

flag=0;

return;

}

double sum=0;

for(int k=i+1;k<=n;k++)

{

sum+=U(i,k)*x[k];

}

x[i]=(y[i]-sum)/U(i,i);

}

break;

case 2:

LUDecomposition(A,flag,L,U);

if(flag<1)

{

return;

}

if(L(1,1)==0)

{

flag=0;

return;

}

y[1]=b[1]/L(1,1);

for(int i=2;i<=n;i++)

{

if(L(i,i)<=0){

flag=0;

return;

}

double sum=0;

for(int k=1;k<=i-1;k++)

{

sum+=L(i,k)*y[k];

}

y[i]=(b[i]-sum)/L(i,i);

}

x[n]=y[n];

for(int i=n-1;i>=1;i--)

{

double sum=0;

for(int k=i+1;k<=n;k++)

{

sum+=U(i,k)*x[k];

}

x[i]=y[i]-sum;

}

break;

}

}

void LinearEquations::Catchup(ColVector&a,ColVector &b,ColVector &c,ColVector &f,int &flag,ColVector &x,int type)

{

flag=1;

int n=b.getRowSize();

if(n!=a.getRowSize()||n!=b.getRowSize()||n!=f.getRowSize())

{

flag=0;

return;

}

if(fabs(b[1])<=fabs(c[1])||fabs(b[n])<=fabs(a[n])||b[1]*c[1]==0||a[n]*b[n]==0)

{

flag=0;

return;

}

for(int i=2;i<=n-1;i++)

if(fabs(b[i])<fabs(a[i])+fabs(c[i])||a[i]*c[i]==0)

{

flag=0;

return;

}

ColVector d(n),u(n),y(n),l(n);

x=ColVector (n);

switch(type){

case 1:

d=c;

u[1]=b[1];

for(int i=2;i<=n;i++)

{

l[i]=a[i]/u[i-1];

u[i]=b[i]-l[i]*c[i-1];

}

y[1]=f[1];

for(int i=2;i<=n;i++)

{

y[i]=f[i]-l[i]*y[i-1];

}

x[n]=y[n]/u[n];

for(int i=n-1;i>=1;i--)

{

x[i]=(y[i]-c[i]*x[i+1])/u[i];

}

break;

case 2:

l[1]=b[1];

for(int i=1;i<=n-1;i++)

{

u[i]=c[i]/l[i];

l[i+1]=b[i+1]-a[i+1]*u[i];

}

y[1]=f[1]/l[1];

for(int i=2;i<=n;i++)

{

y[i]=(f[i]-a[i]*y[i-1])/l[i];

}

x[n]=y[n];

for(int i=n-1;i>=1;i--)

{

x[i]=y[i]-u[i]*x[i+1];

}

break;

}

}

void LinearEquations::JacobiIterativeMethod(Matrix &A,ColVector &b,

double e,ColVector &x0,int MAX, int &flag,ColVector &x){

flag =1;

int n=A.getRowSize();

if(n!=b.getRowSize()||n!=A.getColSize()||n!=x0.getRowSize())

{

flag=0;

return;

}

for(int i=1;i<=n;i++){

if(A(i,i)==0){

flag=0;

return ;

}

}

double eps=0;

int k=0;

int sum=0;

int i,j;

ColVector x1(n);

ColVector dist(n);

while(k<MAX){

for(i=1;i<=n;i++){

double sum=0;

for(j=1;j<=n;j++){

if(j==1){

continue;

}

sum+=A(i,j)*x0[j];

}

x1[i]=(b[i]-sum)/A(i,i);

}

k++;

dist=x1-x0;

eps=dist.norm(3);

cout<<endl;

cout<<"k="<<k<<"\nx1="<<x1<<"x0="<<x0<<endl;

cout<<"dist="<<dist<<endl;

cout<<"eps="<<eps<<endl;

if(eps<=e){

break;

}

else{

x0=x1;

}

}

if(k==MAX){

flag=0;

return;

}

else{

x=x1;

}

}

void LinearEquations::Gauss_SeidelIterativeMethod(Matrix &A,ColVector &b,double e,

ColVector &x0,int MAX, int &flag,ColVector &x){

flag =1;

int n=A.getRowSize();

if(n!=b.getRowSize()||n!=A.getColSize()||n!=x0.getRowSize())

{

flag=0;

return;

}

for(int i=1;i<=n;i++){

if(A(i,i)==0){

flag=0;

return ;

}

}

double eps=0;

int k=0;

ColVector x1(n);

ColVector dist(n);

while(k<MAX){

for(int i=1;i<=n;i++){

double sum=0;

for(int j=1;j<=n;j++){

if(j<i){

sum+=A(i,j)*x1[j];

}

else if(j==i){

continue;

}

else{

sum+=A(i,j)*x0[j];

}

}

x1[i]=(b[i]-sum)/A(i,i);

}

k++;

dist=x1-x0;

eps=dist.norm(3);

cout<<"k="<<k<<"\nx1="<<x1<<"x0="<<x0<<endl;

cout<<"dist="<<dist<<endl;

cout<<"eps="<<eps<<endl;

if(eps<=e){

break;

}

else{

x0=x1;

}

}

if(k==MAX){

flag=0;

return;

}

else{

x=x1;

}

}

运行结果:

【实验心得】

我在实验中使用了间接方法解线性方程组,获得了一些心得。首先,我发现使用间接方法可以简化计算过程,特别适用于方程组较大的情况。通过将方程组转化为矩阵形式,并利用矩阵的运算性质来求解,可以大大减少计算量。其次,我注意到间接方法的精度较高,能够得到比较准确的解。与直接方法相比,间接方法不容易出现舍入误差,因为矩阵运算过程中的舍入误差可以通过精确的结果进行修正。此外,我发现间接方法还可以应用于其他数学问题的求解中,例如线性最小二乘问题等。总体来说,间接方法是一种简单高效、精度较高的解线性方程组的方法,对于数学问题的求解也具有一定的推广价值。通过这次实验,我不仅学到了解线性方程组的间接方法,还深入了解了矩阵运算的原理和应用,对数学问题的求解能力也有了一定的提升。

得 分________

评阅日期________

教师签名________

相关推荐
海码0072 小时前
【Hot 100】94. 二叉树的中序遍历
数据结构·c++·算法·二叉树·hot100
lqjun08273 小时前
矩阵求导常用公式解析:标量、向量与矩阵的导数计算
线性代数·矩阵
大模型铲屎官4 小时前
【深度学习-Day 2】图解线性代数:从标量到张量,理解深度学习的数据表示与运算
人工智能·pytorch·python·深度学习·线性代数·机器学习·llm
小陈爱建模5 小时前
[更新完毕]2025东三省C题深圳杯C题数学建模挑战赛数模思路代码文章教学: 分布式能源接入配电网的风险分析
分布式·数学建模·能源
qq_447429415 小时前
数据结构与算法:图论——并查集
数据结构·算法·图论
搏博10 小时前
机器学习之五:基于解释的学习
人工智能·深度学习·学习·算法·机器学习
耀耀_很无聊12 小时前
02_使用 AES 算法实现文件加密上传至阿里云、解密下载
java·spring boot·算法·阿里云·云计算·aes·oss
江沉晚呤时15 小时前
Redis缓存穿透、缓存击穿与缓存雪崩:如何在.NET Core中解决
java·开发语言·后端·算法·spring·排序算法
achene_ql15 小时前
缓存置换:用c++实现最近最少使用(LRU)算法
开发语言·c++·算法·缓存