草庐IT

基于MATLAB的求解线性方程组(附完整代码和例题)

唠嗑! 2023-04-10 原文

目录

前言

一. 直接求解:矩阵除法

例题1

 例题2

例题3

二. 直接求解:判断求解

2.1 m=n且rank(A)=rank(C)=n

2.2 rank(A)=rank(C)=r<>

例题5

2.3 

三. 矩阵求逆解线性方程组

例题 6


前言

线性方程组的直接解法方法很多,包括Gauss消去法选主元消去法平方根法追赶法等等。但是在MATLAB中,可以直接利用“\”或者“/”来解决问题。这两种方法的内部包含非常多的自适应算法,比如对超定方程使用最小二乘法;对欠定方程给出误差范数最小的一个解;对三对角阵方程组使用追赶法

一. 直接求解:矩阵除法

对线性方程求解,MATLAB调用格式如下:

x=A\B

调用此函数时,矩阵A、B必须具有相同的行数。如果矩阵A没有正确缩放或者接近奇异矩阵,运行代码时,MATLAB就会显示警告信息。

对矩阵A可以分成如下三种情况:

  • 如果A是标量,那么A\B就等同于A.\B
  • 如果A是方阵,B是n行矩阵,那么A\B就是方程A*X=B的解
  • 如果A是矩阵,而且,B是m行矩阵,那么A\B返回方程组A*X=B的最小二乘解

例题1

解如下方程:

解:

MATLAB代码如下:

clc;clear;
A=[0.4096 0.1234 0.3678 0.2943;0.2246 0.3872 0.4015 0.1129;
    0.3645 0.1920 0.3781 0.0643;0.1784 0.4002 0.2786 0.3927];
b=[0.4043;0.1150;0.4240;-0.2557];
x=A\b;
x' %将结果输出为行向量

 运行结果:
ans =

   0.332683779325239  -1.412140862756104   1.602847655449206  -0.500293786006566

 例题2

A为4阶的幻方矩阵,求解线性方程组Ax=b。b的表达式如下:

备注:幻方矩阵的定义:如果一个数组具有相同行列且每行,每列和对角线上的和都一样,则成这些数组则成为魔方矩阵,又叫幻方矩阵。

解:

MATLAB代码如下:

clc;clear;
A=magic(4); %生成四阶的幻方矩阵
b=[34;34;34;34];
x=A\b;
x'

运行结果:

ans =

   0.980392156862745   0.941176470588235   1.058823529411765   1.019607843137255
分析:

4阶的幻方矩阵是奇异矩阵,奇异矩阵也能求解,但是MATLAB会生成警告,警告信息如下:

警告: 矩阵接近奇异值,或者缩放错误。结果可能不准确。RCOND =  4.625929e-18。 

例题3

对线性方程组Ax=b进行求解,并分析是否有误差。A,b矩阵如下:

解:

MATLAB代码如下:

clc;clear;
A=[1 2 0;0 4 3];
b=[8;18];
x=A\b

E=norm(b-A*x) %求范数误差

运行结果:

x =

                   0
   3.999999999999997
   0.666666666666670


E =

     7.160723346098895e-15

分析:此方程属于欠定方程,MATLAB采用最小二乘法进行求解,所以会出现误差

另外最后举一个利用稀疏矩阵对简单线性方程组Ax=B进行求解。

MATLAB代码:

clc;clear;
A=sparse([0 2 0 1 0;4 -1 -1 0 0;0 0 0 3 -6;-2 0 0 0 2;0 0 4 2 0]);%稀疏矩阵
B=sparse([8;-1;-18;8;20]); %稀疏矩阵
x=A\B

E1=norm(B-A*x) %范数误差

运行结果:

x =

   (1,1)      1.000000000000000
   (2,1)      2.000000000000000
   (3,1)      3.000000000000000
   (4,1)      4.000000000000001
   (5,1)      5.000000000000001

E1 =

     4.189529226675416e-15

二. 直接求解:判断求解

给定矩阵A,B如下:

形成解的判定矩阵C如下:

线性方程组有解的判断定理将分成三种情况:


2.1 m=n且rank(A)=rank(C)=n

此时,方程组有唯一的解 

例题4

求解如下方程组:

解:

MATLAB代码如下:

clc;clear;
A=[1 2 3 4;4 3 2 1;1 3 2 4;4 1 3 2];
B=[5 1;4 2;3 3;2 4];
C=[A B];

%判定前提条件
rank_A=rank(A)
rank_C=rank(C)

%求解
x1=inv(A)*B

%计算范数误差
E1=norm(A*x1-B)

%计算精确解
x2=inv(sym(A))*B

%计算范数误差
E2=norm(A*x2-B)

运行结果:

rank_A =4
rank_C = 4


x1 =

  -1.800000000000000   2.399999999999999
   1.866666666666666  -1.266666666666667
   3.866666666666667  -3.266666666666667
  -2.133333333333333   2.733333333333333


E1 =7.291088482824584e-15

 
x2 =
[   -9/5,   12/5]
[  28/15, -19/15]
[  58/15, -49/15]
[ -32/15,  41/15]
 
E2 =0

2.2 rank(A)=rank(C)=r<n

此时方程组有无穷多个解。将原方程组可以转化为对应的齐次方程组的解,形式如下:

此时需要求取A矩阵的化零矩阵,MATLAB格式如下:

Z=null(A)

 或者求取A矩阵的化零矩阵的规范形式,MATLAB格式如下:

Z=null(A,'r')

例题5

求解以下方程组:


解:

MATLAB代码如下:

clc;clear;
A=[1 2 3 4;2 2 1 1;2 4 6 8;4 4 2 2];
B=[1;3;2;6];
C=[A B];

%判断可解性
rank=[rank(A),rank(C)]

%求解出规范化的化零空间
Z=null(sym(A))

%求特解
x0=sym(pinv(A)*B)

%验证得出的解
a1=randn(1);
a2=rand(1); %a1和a2是不同分布的随机数
x1=a1*Z(:,1)+a2*Z(:,2)+x0;
E=norm(double(A*x1-B))

%将通解表示出来
syms a3 a4;
x2=a3*Z(:,1)+a4*Z(:,2)+x0

运行结果:

rank = 2     2

 分析:说明有解,且解不止一个


Z =
[    2,    3]
[ -5/2, -7/2]
[    1,    0]
[    0,    1]
 分析:此结果可以解释为,如下等式:


 
x0 =
 125/131
  96/131
 -10/131
 -39/131
 

E =0

 分析:此方法求出的结果没有误差


x2 =
 
        2*a3 + 3*a4 + 125/131
 96/131 - (7*a4)/2 - (5*a3)/2
                  a3 - 10/131
                  a4 - 39/131

分析:此结果可以写成通式如下:

2.3 

此时只能采用摩尔-彭罗斯(Moore-Penrose)广义逆求解出其最小二乘法,MATLAB格式如下:

x=pinv(A)*B

这种方法只能使误差范数测度||Ax-B||取的最小值,并不能完全符合原始的代数方程。

三. 矩阵求逆解线性方程组

通过反转系数矩阵A,也可以实现对线性方程组Ax=b的求解。不幸的是,与之前反斜杠计算的方法相比,此方法的运算速度会更慢,残差也相对较大。但其实,它也有它的优点,我们来看一道例题。

例题 6

利用八阶的幻方矩阵,来比较MATLAB中x1=A\b和x2=pinv(A)*b两种求解方法的精确度。

解:

MATLAB代码如下:

clc;clear;
A=magic(8);
A1=A(:,1:6); %行数全取,列数保留1~6列,具体原因见"分析"
rank_A1=rank(A1)
b=260*ones(8,1); %260是原A矩阵的幻数和

%使用反斜杠法求解
x1=A1\b
norm_x1=norm(x1)
E1=norm(A1*x1-b)

%使用pinv()函数求解
x2=pinv(A1)*b
norm_x2=norm(x2)
E2=norm(A1*x2-b)

运行结果:

rank_A1 =3

警告: 秩亏,秩 = 3,tol =  1.882938e-13。 
(由于A1矩阵非方阵,所以运算秩时矩阵出现警告,与矩阵秩相关的介绍可以看以下文章)

基于MATLAB的矩阵性质:行列式,秩,迹,范数,特征多项式与矩阵多项式_唠嗑!的博客-CSDN博客

x1 =

   2.999999999999998
   4.000000000000000
                   0
                   0
   1.000000000000002
                   0


norm_x1 = 5.099019513592784
E1 = 1.392373714442771e-13


x2 =

   1.153846153846151
   1.461538461538463
   1.384615384615385
   1.384615384615383
   1.461538461538461
   1.153846153846153


norm_x2 =3.281650616569467
E2 =4.019436694230464e-13

分析:

(1)将A矩阵转换为A1,因为当只有六列时,方程仍然是一致的,依旧存在解,而且解并非全由1组成。另外,由于矩阵低秩,所以会有无数个解。

(2)根据范数误差计算的结果,两种求解方法精度一致

(3)解x1的特殊之处在于它只有三个非零元素;解x2的特殊之处在于它的norm(x2)非常小

有关基于MATLAB的求解线性方程组(附完整代码和例题)的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  3. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  4. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  5. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  6. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  7. 程序员如何提高代码能力? - 2

    前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源

  8. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  9. Matlab imread()读到了什么 (浅显 当复习文档了) - 2

    matlab打开matlab,用最简单的imread方法读取一个图像clcclearimg_h=imread('hua.jpg');返回一个数组(矩阵),往往是a*b*cunit8类型解释一下这个三维数组的意思,行数、数和层数,unit8:指数据类型,无符号八位整形,可理解为0~2^8的数三个层数分别代表RGB三个通道图像rgb最常用的是24-位实现方法,即RGB每个通道有256色阶(2^8)。基于这样的24-位RGB模型的色彩空间可以表现256×256×256≈1670万色当imshow传入了一个二维数组,它将以灰度方式绘制;可以把图像拆分为rgb三层,可以以灰度的方式观察它figure(1

  10. 7个大一C语言必学的程序 / C语言经典代码大全 - 2

    嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来

随机推荐