Guass列主元、平方根法、追赶法求解方程组的C++实现
一,要解决的问题
选用合适的算法,求解三种线性方程组:一般线性方程组,对称正定方程组,三对角线性方程组。
方程略。
二,数值方法
1,使用Guass列主元消去法求解一般线性方程组。
Guass列主元是为了防止Guass消去法中大数吃掉小数而引出的一种线性方程组求解方法,消元时选用一列中绝对值最大的元素作为列主元素。
算法伪代码:
消元过程
回代过程
2,使用平方根法求解对称正定方程组
平方根法。它把系数矩阵(对称正定矩阵)表示成一个下三角矩阵L和其转置的乘积的分解。这样的分解又称为Cholesky分解。
3,使用追赶法求解三对角线性方程组
三对角线性方程组是指这一类的线性方程组:系数矩阵是一个对角占优的三对角矩阵。追赶法是专门用来求解三对角线性方程组的,它将系数矩阵分解成alpha矩阵和beta矩阵的乘积,例如以下图所看到的:
三。算法
1。Guass列主元消去法
/*
CreateOn:2016/03/20
Author:linxiaobai
Function:linear equation solution
solution1:列主元Guass消去法求解一般线性方程组
*/
#include "stdafx.h"
# include<iostream>
# include<algorithm>
# include<fstream>
# include<iomanip>
# include<cmath>
using namespace std;
double a[15][15];
const int N=10;
double res[N+1];
void printArry(double a[][15])//打印增广矩阵
{
for(int i=1;i<=10;i++)
{
for(int j=1;j<=11;j++)
{
cout<<setw(3)<<a[i][j]<<" ";
}
cout<<endl;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
cout<<"【运用列主元Guass求解一般线性方程组】"<<endl;
//读入增广矩阵
ifstream in;
in.open("data.txt");
if(!in)
{
cerr<<"file open failed!"<<endl;
return 0;
}
double x;
int i=1,j=1;
while(!in.eof())
{
in>>a[i][j];
j++;
if(j>11)
{
i++;j=1;
}
}
cout<<"增广矩阵:"<<endl<<"++++++++++++++++++++++++++"<<endl;
printArry(a);
cout<<"++++++++++++++++++++++++++";
for(int k=1;k<=N-1;k++)
{
double tmp=abs(a[k][k]);
int ind=k;
for(int j=k;j<=N;j++)//找绝对值最大的行
{
if(abs(a[j][k])>tmp)
{tmp=abs(a[j][k]);ind=j;}
}
//若a[ind][k]=0,停止计算
if(a[ind][k]==0){cout<<"no unique solution"<<endl;return 0;}
//绝对值最大的行交换到第k行
if(ind!=k)
for(int j=1;j<=N+1;j++)
swap(a[ind][j],a[k][j]);
//消元计算
double p;
for(int i=k+1;i<=N;i++)
{
p=a[i][k]/a[k][k];
for(int j=k;j<=N+1;j++)
a[i][j]-=p*a[k][j];
}
}
if(a[N][N]==0)
{cout<<"no unique solution"<<endl;return 0;}
//回代求解
res[N]=a[N][N+1]/a[N][N];
double s;
for(int i=N-1;i>=1;i--)
{
s=0;
for(int j=i+1;j<=N;j++)
s+=a[i][j]*res[j];
res[i]=(a[i][N+1]-s)/a[i][i];
}
//输出解向量为
cout<<endl<<endl<<"解向量为:"<<endl;
for(int i=1;i<=N;i++)
if(abs(res[i])<10e-14)
cout<<"0"<<" ";
else
cout<<res[i]<<" ";
cout<<endl;
return 0;
}
2,使用平方根算法解对称正定方程组
/*
CreateOn:2016/03/20
Author:linxiaobai
Function:linear equation solution
solution1:使用平方根算法解对称正定方程组
*/
# include"stdafx.h"
# include<iostream>
# include<fstream>
# include<cmath>
# include<iomanip>
using namespace std;
double a[10][10];
const int N=8;
double b[N+1],xx[N+1],yy[N+1];
void printArry(double a[][10])//输出系数矩阵
{
for(int i=1;i<=8;i++)
{
for(int j=1;j<=8;j++)
{
cout<<setw(3)<<a[i][j]<<" ";
}
cout<<endl;
}
}int main()
{
cout<<"【运用平方根算法解对称正定方程组】"<<endl;
/*读入系数矩阵*/
ifstream in;
in.open("data2.txt");
if(!in)
{
cerr<<"file open failed!"<<endl;
return 0;
}
int i=1,j=1;
while(i<=N)
{
in>>a[i][j];
j++;
if(j>8)
{
i++;j=1;
}
}
/*读入b[]*/
for(int i=1;i<=N;i++)
in>>b[i];
cout<<"系数矩阵:"<<endl<<"++++++++++++++++++++++++++"<<endl;
printArry(a);
cout<<endl<<endl<<"b:"<<endl;
for(int i=1;i<=N;i++)
cout<<setw(3)<<b[i]<<" ";
cout<<endl<<"++++++++++++++++++++++++++";
//開始计算。A=GG',G存在A的下三角
for(int k=1;k<=N;k++)
{
double s1=0;
for(int m=1;m<=k-1;m++)
s1+=pow(a[k][m],2);
a[k][k]=sqrt(a[k][k]-s1);
for(int i=k+1;i<=N;i++)
{
double s2=0;
for(int m=1;m<=k-1;m++)
s2+=a[i][m]*a[k][m];
a[i][k]=(a[i][k]-s2)/a[k][k];
}
//计算y
double s3=0;
for(int m=1;m<=k-1;m++)
s3+=a[k][m]*yy[m];
yy[k]=(b[k]-s3)/a[k][k];
}
//计算x
xx[N]=yy[N]/a[N][N];
for(int k=N-1;k>=1;k--)
{
double s4=0;
for(int m=k+1;m<=N;m++)
s4+=a[m][k]*xx[m];
xx[k]=(yy[k]-s4)/a[k][k];
}
cout<<endl<<"解向量为:"<<endl;
for(int i=1;i<=N;i++)
cout<<setw(3)<<xx[i]<<" ";
cout<<endl;
return 0;
}
3,使用追赶法解三对角线性方程组
/*
CreateOn:2016/03/20
Author:linxiaobai
Function:linear equation solution
solution1:使用追赶法解三对角线性方程组
*/
# include"stdafx.h"
# include<iostream>
# include<fstream>
# include<iomanip>
# include<cmath>
using namespace std;
const int N=10;
double a[N+1],c[N+1],d[N+1],xx[N+1],yy[N+1];
int main()
{
cout<<"【运用追赶法解三对角线性方程组】"<<endl;
//a[N]:主对角线上的元素
for(int i=1;i<=N;i++)
a[i]=4;
//c[N]:上辅对角线上的元素
for(int i=1;i<=N-1;i++)
c[i]=-1;
//d[N]:下辅对角线上的元素
for(int i=2;i<=N;i++)
d[i]=-1;
double b[]={0,7,5,-13,2,6,-12,14,-4,5,-5};
cout<<"++++++++++++++++++++++++++"<<endl;
cout<<"主对角线上的元素a:"<<endl;
for(int i=1;i<=N;i++)
cout<<setw(3)<<a[i]<<" ";
cout<<endl<<endl<<"上辅对角线上的元素c:"<<endl;
for(int i=1;i<=N-1;i++)
cout<<setw(3)<<c[i]<<" ";
cout<<endl<<endl<<"下辅对角线上的元素d:"<<endl;
for(int i=2;i<=N;i++)
cout<<setw(3)<<d[i]<<" ";
cout<<endl<<endl<<"b:"<<endl;
for(int i=1;i<=N;i++)
cout<<setw(3)<<b[i]<<" ";
cout<<endl<<"++++++++++++++++++++++++++"<<endl;
/*開始计算*/
double alpha[N+1],beta[N+1];
alpha[1]=a[1];
for(int i=1;i<=N-1;i++)
{
beta[i]=c[i]/alpha[i];
alpha[i+1]=a[i+1]-d[i+1]*beta[i];
}
yy[1]=b[1]/alpha[1];
for(int i=2;i<=N;i++)
{
yy[i]=(b[i]-d[i]*yy[i-1])/alpha[i];
}
xx[N]=yy[N];
for(int i=N-1;i>=1;i--)
xx[i]=yy[i]-beta[i]*xx[i+1];
//解向量为:
cout<<endl<<"解向量为:"<<endl;
for(int i=1;i<=N;i++)
if(abs(xx[i])<10e-14)
cout<<"0"<<" ";
else
cout<<xx[i]<<" ";
cout<<endl;
return 0;
}
四,数值结果
1,Guass列主元消去法
2,使用平方根算法解对称正定方程组
3,使用追赶法解三对角线性方程组
五,结果分析与实验总结
浮点计算产生的误差
在Guass消元算法之前的代码中,我使用了近似的方法,将绝对值小于10的-14次方的值近似为0,如今去掉这个处理。来看一下结果:
for(int i=1;i<=N;i++)
//if(abs(res[i])<10e-14)
//cout<<"0"<<" ";
//else
cout<<res[i]<<" ";
能够看到x3的值是一个十分接近于0的数,假设将消元后的系数矩阵打印出来。能够看到消元后的系数矩阵并非一个真正的上三角矩阵,下三角部分有几处的值是一个绝对值极小的值。这是因为计算机的浮点计算造成的,浮点数在计算机中本身就不是一个精确的数,在消元的过程中。一些浮点运算有误差,于是最后得到的是近似值,而不是0。
同理,平方根法和追赶法也会产生由浮点数计算引起的误差,降低计算误差正是学习数值分析的目的。
Guass列主元、平方根法、追赶法求解方程组的C++实现的更多相关文章
- 用列主元消去法分别解方程组Ax=b,用MATLAB程序实现(最有效版)
数值分析里面经常会涉及到用MATLAB程序实现用列主元消去法分别解方程组Ax=b 具体的方法和代码以如下方程(3x3矩阵)为例进行说明: 用列主元消去法分别解方程组Ax=b,用MATLAB程序实现: ...
- 插值代码17个---MATLAB
函数名 功能Language 求已知数据点的拉格朗日插值多项式Atken 求已知数据点的艾特肯插值多项式Newton 求已知数据点的均差形式的牛顿插值多项式Newtonforward 求已知数据点的前 ...
- MATLAB求解方程与方程组
1. solve函数 ①求解单个一元方程的数值解 syms x; x0 = double(solve(x +2 - exp(x),x)); 求x+2 = exp(x)的解,结果用double ...
- fslove - Matlab求解多元多次方程组
fslove - Matlab求解多元多次方程组 简介: 之前看到网上的一些资料良莠不齐,各种转载之类的,根本无法解决实际问题,所以我打算把自己的学到的总结一下,以实例出发讲解fsolve. 示例如下 ...
- 高斯消去、追赶法 matlab
1. 分别用Gauss消去法.列主元Gauss消去法.三角分解方法求解方程组 程序: (1)Guess消去法: function x=GaussXQByOrder(A,b) %Gauss消去法 N = ...
- (原创)列主元Gauss消去法的通用程序
import numpy as np np.set_printoptions(precision=5) A = np.array([[31., -13., 0., 0., 0., -10., 0., ...
- MDP中值函数的求解
MDP概述 马尔科夫决策过程(Markov Decision Process)是强化学习(reinforcement learning)最基本的模型框架.它对序列化的决策过程做了很多限制.比如状态 ...
- 实现求解线性方程(矩阵、高斯消去法)------c++程序设计原理与实践(进阶篇)
步骤: 其中A是一个n*n的系数方阵 向量x和b分别是未知数和常量向量: 这个系统可能有0个.1个或者无穷多个解,这取决于系数矩阵A和向量b.求解线性系统的方法有很多,这里使用一种经典的方法——高斯消 ...
- python实现迭代法求方程组的根
有方程组如下: 迭代法求解x,python代码如下: import numpy as np import matplotlib.pyplot as plt A = np.array([[8, -3, ...
随机推荐
- Android(java)学习笔记194:ContentProvider使用之获得系统联系人信息02(掌握)
1.重要: 系统删除一个联系人,默认情况下并不是把这个联系人直接删除掉了,只是做了一个标记,标记为被删除. 2.前面一讲说过了如何获取系统联系人信息(通过ContentProvider),获取联系人信 ...
- Java入门第38课——猜字母游戏之设计程序结构
问题 本案例需要实现猜字母游戏程序中的程序结构 方案 分析猜字母游戏可以看出,程序首先需要随机产生5个不同的字母作为需要猜测的结果,因此,可以先定义一个方法,以实现此功能: ...
- CREATE VIEW - 定义一个视图
SYNOPSIS CREATE [ OR REPLACE ] VIEW name [ ( column_name [, ...] ) ] AS query DESCRIPTION 描述 CREATE ...
- CREATE SEQUENCE - 创建一个新的序列发生器
SYNOPSIS CREATE [ TEMPORARY | TEMP ] SEQUENCE name [ INCREMENT [ BY ] increment ] [ MINVALUE minvalu ...
- JavaScipt30(第二十二个案例)(主要知识点:getBoundingClientRect)
这是第二十二个案例,这个例子实现的是鼠标移入a标签时,将其高亮. 附上项目链接: https://github.com/wesbos/JavaScript30 以下为注释后的源码: <scrip ...
- php 阿里云短信验证码
阿里云短信服务:https://dysms.console.aliyun.com 1.准备 1.1.创建签名.模板 1.2.创建.使用阿里云秘钥 地址:https://usercenter.conso ...
- Python 迭代器-生成器-面向过程编程
上节课复习:1. 函数的递归调用 在调用一个函数的过程中又直接或者间接地调用了函数本身称之为函数的递归 函数的递归调用有两个明确的阶段: 1. 回溯 一层一层地调用本身 注意: 1.每一次调用问题的规 ...
- python爬虫学习,使用requests库来实现模拟登录4399小游戏网站。
1.首先分析请求,打开4399网站. 右键检查元素或者F12打开开发者工具.然后找到network选项, 这里最好勾选perserve log 选项,用来保存请求日志.这时我们来先用我们的账号密码登陆 ...
- PAT 1073. 多选题常见计分法
PAT 1073. 多选题常见计分法 批改多选题是比较麻烦的事情,有很多不同的计分方法.有一种最常见的计分方法是:如果考生选择了部分正确选项,并且没有选择任何错误选项,则得到50%分数:如果考生选择了 ...
- Spring AOP配置简单记录(注解及xml配置方式)
在了解spring aop中的关键字(如:连接点(JoinPoint).切入点(PointCut).切面(Aspact).织入(Weaving).通知(Advice).目标(Target)等)后进行了 ...