<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>神社的储物间</title>
  <icon>https://mxts.jiujiuer.xyz/icon.png</icon>
  <subtitle>*节操消失了*</subtitle>
  <link href="https://mxts.jiujiuer.xyz/atom.xml" rel="self"/>
  
  <link href="https://mxts.jiujiuer.xyz/"/>
  <updated>2026-05-28T06:52:01.719Z</updated>
  <id>https://mxts.jiujiuer.xyz/</id>
  
  <author>
    <name>xeonds</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>自编码器与变分自编码器</title>
    <link href="https://mxts.jiujiuer.xyz/2024/04/28/%E8%87%AA%E7%BC%96%E7%A0%81%E5%99%A8%E4%B8%8E%E5%8F%98%E5%88%86%E8%87%AA%E7%BC%96%E7%A0%81%E5%99%A8/"/>
    <id>https://mxts.jiujiuer.xyz/2024/04/28/%E8%87%AA%E7%BC%96%E7%A0%81%E5%99%A8%E4%B8%8E%E5%8F%98%E5%88%86%E8%87%AA%E7%BC%96%E7%A0%81%E5%99%A8/</id>
    <published>2024-04-28T16:00:00.000Z</published>
    <updated>2026-05-28T06:52:01.719Z</updated>
    
    <content type="html"><![CDATA[<iframe src="https://docs.google.com/viewer?url=https://raw.githubusercontent.com/anka-afk/anka-afk.github.io/08ad771c8c9e9616553c59276049e0117c3f36ec/autoencoder.pdf&embedded=true" width="100%" height="600px"></iframe>]]></content>
    
    
    <summary type="html">自编码器</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>Gauss-Seidel迭代法</title>
    <link href="https://mxts.jiujiuer.xyz/2024/04/17/Gauss-Seidel%E8%BF%AD%E4%BB%A3%E6%B3%95/"/>
    <id>https://mxts.jiujiuer.xyz/2024/04/17/Gauss-Seidel%E8%BF%AD%E4%BB%A3%E6%B3%95/</id>
    <published>2024-04-17T16:00:00.000Z</published>
    <updated>2026-05-28T06:52:01.690Z</updated>
    
    <content type="html"><![CDATA[<p>#定义<br>也称高斯-赛德尔迭代法<br>观察 $Jacobi$ 迭代法, 我们发现, 在求 $\color{red}{x^{(k+1)}}\text{ }$ 的分量时,<br>当求到第 $i$ 个分量: $\color{red}{x_i^{(k+1)}}$ 时, 我们已经求到了 $x_{1}^{(k+1)},x_{2}^{(k+1)}\cdots x_{i-1}^{(k+1)}$<br>我们知道, $x_{1}^{(k+1)},x_{2}^{(k+1)}\cdots x_{i-1}^{(k+1)}$ 理论上是比 $x_{1}^{(k)},x_{2}^{(k)}\cdots x_{i-1}^{(k)}$ 要接近<font color="#ff0000">真值</font>的,<br>我们不禁想到, 如果用 $x_{1}^{(k+1)},x_{2}^{(k+1)}\cdots x_{i-1}^{(k+1)}$ 代替 $x_{1}^{(k)},x_{2}^{(k)}\cdots x_{i-1}^{(k)}$<br>会不会使得迭代法收敛更快呢?<br>(毕竟使用了更加接近真值的信息)</p><ul><li><p>如果将 Jacobi 迭代法得到的解立刻投入到下一次运算中, 我们得到<strong>高斯-赛德尔迭代法</strong></p><p>  基于上面的想法, 我们对 $Jacobi$ 方法进行改造得到</p></li></ul><p>$\begin{cases}\mathrm{<del>x}<em>1^{(k+1)}&#x3D;\frac1{a</em>{11}}(-a_{12}\mathrm{x}<em>2^{(k)}-a</em>{13}\mathrm{x}<em>3^{(k)}-a</em>{14}\mathrm{x}<em>4^{(k)}-\cdots-a</em>{1n}\mathrm{x}_n^{(k)}+b_1)\\\mathrm{</del>x}<em>2^{(k+1)}&#x3D;\frac1{a</em>{22}}(-a_{21}\mathrm{x}<em>1^{(k+1)}-a</em>{23}\mathrm{x}<em>3^{(k)}-a</em>{24}\mathrm{x}<em>4^{(k)}-\cdots-a</em>{2n}\mathrm{x}<em>n^{(k)}+b_2)\\\mathrm{~x}<em>3^{(k+1)}&#x3D;\frac1{a</em>{33}}(-a</em>{31}\mathrm{x}<em>1^{(k+1)}-a</em>{32}\mathrm{x}<em>2^{(k+1)}-a</em>{34}\mathrm{x}<em>4^{(k)}-\cdots-a</em>{3n}\mathrm{x}<em>n^{(k)}+b_3)\\\cdots&amp;\cdots&amp;\cdots\\\mathrm{~x}<em>n^{(k+1)}&#x3D;\frac1{a_m}\left(-a</em>{n1}\mathrm{x}<em>1^{(k+1)}-a</em>{n2}\mathrm{x}<em>2^{(k+1)}-a</em>{n2}\mathrm{x}<em>3^{(k+1)}-\cdots-a</em>{m-1}\mathrm{x}</em>{n-1}^{(k+1)}+b_n\right)&amp;\end{cases}$<br>$x_i^{(k)}&#x3D;\frac{1}{a_{ii}}\left[-\sum_{j&#x3D;1}^{i-1}(a_{ij}x_j^{(k)})-\sum_{j&#x3D;i+1}^{n}(a_{ij}x_j^{(k-1)})+b_i\right],$</p><ul><li>看起来确实很丑, 但是推导是容易的<br>我们来看比较好看的矩阵形式:<blockquote><p>$\begin{aligned}&amp;x^{(k+1)} &#x3D; -D^{-1}(Lx^{(k+1)} +Ux^{(k)}) + D^{-1}b \ &amp;\Rightarrow x^{(k&#x3D;1)}&#x3D; -(D+L)^{-1}Ux^{(k)}+(D+L)^{-1}b\end{aligned}$</p></blockquote></li><li>推导是很直观的, $x_{i}^{(k+1)}$ 的系数都是矩阵 $A$ 的下三角部分<br>而 $x_{i}^{(k)}$ 的系数都是矩阵的上三角部分</li></ul><h1 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h1><p>#性质</p><ul><li>这个迭代法的想法是, $x^{(k+1)}$﻿是比 $x^{(k)}$﻿更加接近精确解 $x^*$﻿的, 我们就直接利用当前算出的一些 $x^{(k+1)}$﻿的分量计算其他分量, 例如算 $x^{(k+1)}_2$﻿时, 我们已经算出 $x^{(k+1)}_1$﻿了, 我们可以用这个代替 $x^{k}_1$﻿来计算 $x^{(k+1)}_2$﻿, 因为 $x_1^{(k+1)}$﻿更加接近精确解的第一个分量.</li><li>因为我们是根据当前步骤已经算出的分量算其他的分量, 所以这个方法的解的分量 $x_i$﻿<strong>有先后之分</strong></li><li>一般来说这个方法比 Jacobi 迭代法<strong>收敛更快</strong></li></ul><h1 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h1><p>#例子<br>$\begin{cases}10x_1-2x_2-x_3&#x3D;3\-2x_1+10x_2-x_3&#x3D;15\-x_1-2x_2+5x_3&#x3D;10&amp;\end{cases}$<br>经过高斯-赛德尔迭代法得到的迭代公式:<br>$$\begin{aligned}<br>\left|x_1^{(k+1)}\right.&amp;&#x3D;\frac 1{10}(2{x_2}^{(k)}+{x_3}^{(k)}+3) \<br>\left|x_2^{(k+1)}\right.&amp;&#x3D;\frac 1{10}(2{x_1}^{(k+1)}+{x_3}^{(k)}+15) \<br>\left|x_3^{(k+1)}\right.&amp; &#x3D;\frac 15 ({x_1}^{(k+1)}+2{x_2}^{(k+1)}+10)<br>\end{aligned}$$</p><h1 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h1><p>$\varepsilon$ 为精度要求，$k$ 记录迭代次数，$N$ 为允许的最大迭代次数，二维数组 ${a_{ij}}<em>{i,j&#x3D;1}^{n+1}$ 存放 $A,b$. 一维数组 ${x_i}</em>{i&#x3D;1}^n$ 开始存放初值，迭代过程存放迭代值。</p><ol><li>$\color{red}{k&#x3D;0}$ </li><li>对 $\color{red}{i&#x3D;1,2\cdots n}$, 置初值 $x_i&#x3D;0$</li><li>$\color{red}{k&#x3D;k+1}$</li><li>若 $\color{red}{k&gt;N}$, 则输出当前迭代值 $x_{i}$ 和 $k$, 停机</li><li>$\quad P_0&#x3D;0$</li><li>对 $\color{red}{i&#x3D;1,2\cdots n}$<br>$P\leftarrow\Delta x_i&#x3D;(a_{i,n+1}-\sum_{j&#x3D;1}^{n}\alpha_{ij}x_j)&#x2F;\alpha_{ii}^{}$<br>若 $|P_0|&lt;|P|$, 则 $P_0&#x3D;P$<br>$\color{red}{x_i&#x3D;x_i+P}$</li><li>如果 $\color{red}{|P_0|&lt;\varepsilon}$, 则进入步骤 8，否则转入步骤3</li><li>输出近似解 $\quad\text{}\color{red}{x_i(i&#x3D;1,2\cdots n)}$ 和 $k$</li></ol>]]></content>
    
    
    <summary type="html">一种迭代方法</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>jacobi迭代法</title>
    <link href="https://mxts.jiujiuer.xyz/2024/04/17/Jacobi%E8%BF%AD%E4%BB%A3%E6%B3%95/"/>
    <id>https://mxts.jiujiuer.xyz/2024/04/17/Jacobi%E8%BF%AD%E4%BB%A3%E6%B3%95/</id>
    <published>2024-04-17T16:00:00.000Z</published>
    <updated>2026-05-28T06:52:01.690Z</updated>
    
    <content type="html"><![CDATA[<p>#定义 </p><blockquote><p>把系数矩阵写为 $A&#x3D;D+L+U$﻿的形式</p><p>其中 $D$﻿为 $A$﻿的主对角线组成的<strong>对角矩阵</strong></p><p>$L$﻿为 $A$﻿的严格下三角部分组合的<strong>严格下三角矩阵</strong>(不含对角线)</p><p>$U$﻿为 $A$﻿的严格上三角部分组合的<strong>严格上三角矩阵</strong>(不含对角线)</p><p>我们把迭代表达式写为:</p><p>$x^{(k+1)} &#x3D; -D^{-1}(L+U)x^{(k)} + D^{-1}b$</p><p>我们称这种迭代方法为<strong>Jacobi 迭代法</strong></p></blockquote><h1 id="怎么构造-Jacobi-迭代公式"><a href="#怎么构造-Jacobi-迭代公式" class="headerlink" title="怎么构造 Jacobi 迭代公式"></a>怎么构造 Jacobi 迭代公式</h1><p>由方程组 $AX &#x3D; b$ 的第 i 个方程解出 $X_i\left (i&#x3D;1,2,\cdots, n\right)$ 得到一个同解方程组</p><p>$\begin{cases}x_1&#x3D;\dfrac{1}{a_{11}}(-a_{12}x_2-a_{13}x_3-\cdots-a_{1n}x_n+b_1)\[2ex]x_2&#x3D;\dfrac{1}{a_2}(-a_{21}x_1-a_{23}x_3-\cdots-a_{2n}x_n+b_2)\[2ex]……\x_n&#x3D;\dfrac{1}{a_{n1}}(-a_{n1}x_1-a_{n2}x_2-\cdots-a_{n,n-1}x_{n-1}+b_n)\end{cases}$</p><p>我们修改一下右边的 $x_{i}$, 得到迭代公式:</p><p>$\begin{cases}x_{1}^{(k+1)}&#x3D;\frac{1}{a_{11}}(-a_{12}x_{2}^{(k)}-a_{13}x_{3}^{(k)}-\cdots-a_{1n}x_{n}^{(k)}+b_{1})\\x_{2}^{(k+1)}&#x3D;\frac{1}{a_{22}}\big(-a_{21}x_{1}^{(k)}-a_{23}x_{3}^{(k)}-\cdots-a_{2n}x_{n}^{(k)}+b_{2}\big)\\cdots\cdots\x_{n}^{(k+1)}&#x3D;\frac{1}{a_{nm}}\big(-a_{n1}x_{1}^{(k)}-a_{n2}x_{2}^{(k)}-\cdots-a_{n,n-1}x_{n-1}^{(k)}+b_{n}\big)\end{cases}$</p><p>我们有了迭代公式, 总得有一个起点吧<br>#符号<br>我们找一个初始向量: $X^{(0)}&#x3D;(x_1^{(0)},x_2^{(0)},\cdots,x_n^{(0)})^T$</p><p><font color="#ff0000">上面的公式就称为</font> $Jacobi$ <font color="#ff0000">迭代公式</font></p><h2 id="矩阵形式"><a href="#矩阵形式" class="headerlink" title="矩阵形式"></a>矩阵形式</h2><p>#符号<br>我们引入三个记号:</p><p>我们用 $D$ 记矩阵 $A$ 的对角线部分:</p><p>$D&#x3D;\begin{bmatrix}a_{11}&amp;&amp;&amp;\&amp;a_{22}&amp;&amp;\&amp;&amp;\ddots&amp;\&amp;&amp;&amp;a_{nn}\end{bmatrix}$<br>我们用 $L$ 记矩阵 $A_{}$ 的下三角部分<font color="#ff0000">(不包括对角线) </font>:<br>$L&#x3D;\begin{bmatrix}\mathbf{0}\a_{21}&amp;\mathbf{0}\\cdots&amp;\cdots\a_{n1}&amp;a_{n2}&amp;\cdots&amp;\mathbf{0}\end{bmatrix}$<br>我们用 $U_{}$ 记矩阵 $A$ 的上三角部分 <font color="#ff0000">(不包括对角线)</font> :<br>$U&#x3D;\begin{bmatrix}0&amp;a_{12}&amp;\cdots&amp;a_{1n}\&amp;0&amp;\cdots&amp;a_{2n}\&amp;&amp;&amp;\vdots\&amp;&amp;&amp;\mathbf{0}\end{bmatrix}$</p><p>则有 $A{&#x3D;}D{+}L{+}U$ 成立，矩阵形式为</p><p>$$<br>{Dx&#x3D;-(L+U)x+b}<br>$$<br>等式两边乘以 $D^{-1}$, 得</p><p>$x&#x3D;-D^{-1}(L+U)$ $x+D^{-1}b$</p><p>#定义<br>于是我们得到迭代公式:<br>$x^{(k+1)}&#x3D;-D^{-1}{(L+U)}x^{(k)}+D^{-1}b$</p><p>如果不用矩阵形式, 还可以表示为:</p><blockquote><p>$\begin{aligned}x^{(0)} &#x3D; (x_1^{(0)},x_2^{(0)},\cdots,x_n^{(0)})^T \ x_i^{(k+1)} &#x3D; (b_i-\sum_{j&#x3D;1,j\ne i }^na_ijx_j^{(k)})&#x2F;a_{ii} \ i&#x3D;1,2,\cdots,n \quad k &#x3D; 0,1,2,\cdots \quad k表示迭代次数\end{aligned}$</p></blockquote><h1 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h1><p>#性质</p><ul><li>$\text{迭代矩阵 }B_J&#x3D;-D^{-1}(L+U)$</li><li>每迭代一次主要是计算一次矩阵乘向量 $B_Jx^{(k)}$ 所以计算量为 $n^2$ 数量级。</li><li>计算过程中涉及到的中间变量 $x^{(k)}$ 及 $x^{(k+1)}$,需要两组工作单元 $x_{n}$, $y_{n}$来存储}</li><li>$\text{计算过程中,初始数据A始终不变;}$</li><li>解的分量 $ｘ_i$﻿没有先后之分, 适合并行运算</li><li>公式简单, 迭代矩阵容易求到</li><li>也称<font color="#ff0000">同事替换法</font>(相较于后面的方法)</li></ul><h1 id="迭代终止条件"><a href="#迭代终止条件" class="headerlink" title="迭代终止条件"></a>迭代终止条件</h1><p>$\text{若迭代矩阵}\mathsf{B}\text{满足}|B|&lt;1\text{则}$<br>$\left|X^*-X^{(k)}\right|\leq\frac{\left|B\right|}{1-\left|B\right|}\left|X^{(k)}-X^{(k-1)}\right|$</p><ul><li>这个公式给出了误差的估计, 也就是迭代点和真值的差距可以用两个相邻迭代点的差距约束<br>于是我们有一个停止迭代的条件 (终止条件)<br>$$\left|X^{(k-1)}- X^{(k-1)}\right|&lt;\varepsilon $$</li></ul><h1 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h1><p>#例子<br>$\begin{cases}10x_1-2x_2-x_3&#x3D;3\-2x_1+10x_2-x_3&#x3D;15\-x_1-2x_2+5x_3&#x3D;10&amp;\end{cases}$<br>求 $Jacobi$ 迭代公式<br>就是第 $i$ 行把其他元素都移到右边, 左边剩 $x_{i}$, 然后把左边的变成 $x_{i}^{(k+1)}$, 右边的变成 $x_{i}^{(k)}$<br>得到</p><p>$$\begin{gathered}<br>x_{1}^{(k+1)}&#x3D;\frac{1}{10}(2{x_2}^{(k)}+{x_3}^{(k)}+3) \<br>x_{2}^{(k+1)}&#x3D;\frac1{10}(2{x_1}^{(k)}+{x_3}^{(k)}+15) \<br>x_{3}^{(k+1)}&#x3D;\frac15{(x_1^{(k)}+2x_2^{(k)}+10)}<br>\end{gathered}$$</p><h1 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h1><p>#代码</p><figure class="highlight matlab"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">y</span>=<span class="title">jacobi</span><span class="params">(A,b,x,M)</span></span></span><br><span class="line">D = <span class="built_in">diag</span>(<span class="built_in">diag</span>(A));</span><br><span class="line">U = -<span class="built_in">triu</span>(A,<span class="number">1</span>)</span><br><span class="line">L = -<span class="built_in">tril</span>(A,<span class="number">-1</span>);</span><br><span class="line">B = D\(L+U)</span><br><span class="line">f= D\b;</span><br><span class="line">y = B*x+f ; n=<span class="number">1</span>:</span><br><span class="line"><span class="keyword">while</span> norm(y-x)&gt;=<span class="number">1.0e-6</span>&amp;n&lt;M</span><br><span class="line">x= y</span><br><span class="line">y=B*x+f;</span><br><span class="line">n=n+<span class="number">1</span>;</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">一种迭代方法</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>Rust学习</title>
    <link href="https://mxts.jiujiuer.xyz/2024/04/17/Rust/"/>
    <id>https://mxts.jiujiuer.xyz/2024/04/17/Rust/</id>
    <published>2024-04-17T16:00:00.000Z</published>
    <updated>2026-05-28T06:52:01.707Z</updated>
    
    <content type="html"><![CDATA[<p>参考视频：【Rust 编程语言入门教程（Rust 语言&#x2F;Rust 权威指南配套）【已完结】】 <a href="https://www.bilibili.com/video/BV1hp4y1k7SV/?p=12&amp;share_source=copy_web&amp;vd_source=faa4d83326aa65fa16123ce1d49425a3">https://www.bilibili.com/video/BV1hp4y1k7SV/?p=12&amp;share_source=copy_web&amp;vd_source=faa4d83326aa65fa16123ce1d49425a3</a></p><p>我将采用注释式笔记, 也就是所有知识都用代码文件存放, 在注释中写明知识点</p><p>[[猜数游戏]]<br>[[rust变量类型]]</p>]]></content>
    
    
    <summary type="html">好东西</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>Rust变量类型</title>
    <link href="https://mxts.jiujiuer.xyz/2024/04/17/rust%E5%8F%98%E9%87%8F%E7%B1%BB%E5%9E%8B/"/>
    <id>https://mxts.jiujiuer.xyz/2024/04/17/rust%E5%8F%98%E9%87%8F%E7%B1%BB%E5%9E%8B/</id>
    <published>2024-04-17T16:00:00.000Z</published>
    <updated>2026-05-28T06:52:01.719Z</updated>
    
    <content type="html"><![CDATA[<figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;Hello, world!&quot;</span>);</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 不可变变量</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">x</span> = <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;x的值是:&#123;&#125;&quot;</span>,x);</span><br><span class="line"></span><br><span class="line">    x = <span class="number">6</span>;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;x的值是:&#123;&#125;&quot;</span>,x);</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 常量也是不可变的,但是不可约使用mut,永远都不可变</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 声明常量必须使用const</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 声明常量必须标注类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 常量可以在任何作用域声明,包括全局作用域</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 常量只能被设置为常量表达式,不能是函数调用的结果,或任何其他只能在运行时计算得到的值</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 常量在运行期间总是存在的,并且它们在任何作用域中都可以被访问</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 常量使用全大写字母和下划线命名,并且下划线可以用来增加可读性</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 数字中间可以插入下划线来增加可读性</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> MAX_POINTS:<span class="type">u32</span> = <span class="number">100_000</span>;</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 隐藏变量</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 可以用同样的名字声明一个新变量,而新变量会隐藏之前的变量</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">x</span> = <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;x的值是:&#123;&#125;&quot;</span>,x);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">x</span> = x + <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;x的值是:&#123;&#125;&quot;</span>,x);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 虽然x是不可变的,但是可以用let关键字来声明一个新变量,这样就可以隐藏之前的变量</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 相当于override</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">x</span> = x * <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;x的值是:&#123;&#125;&quot;</span>,x);</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// shadow和把变量标记为mut是不一样的</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 用let声明的新变量也是不可变的</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 使用let声明的同名新变量的类型可以和之前的不一样</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">spaces</span> = <span class="string">&quot;    &quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">spaces</span> = spaces.<span class="title function_ invoke__">len</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 这里把spaces的类型从字符串变成了数字,但是名字还是spaces,其实是一个新的变量,同名隐藏掉原来的变量</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 如果这里不加let,会报错,因为变量是不可变的</span></span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;spaces的值是:&#123;&#125;&quot;</span>,spaces);</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 数据类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// Rust是静态类型语言,必须在编译时知道所有变量的类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 如果可能的类型比较多,例如parse方法,就必须添加类型的标注</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">guess</span>:<span class="type">u32</span> = <span class="string">&quot;43&quot;</span>.<span class="title function_ invoke__">parse</span>().<span class="title function_ invoke__">expect</span>(<span class="string">&quot;不是个数!&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 如果不标注是u32类型,会报错</span></span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;guess的值是:&#123;&#125;&quot;</span>,guess);</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 标量类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 标量类型代表单个的值</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// rust一共有四个主要的标量类型:整数,浮点数,布尔类型,字符类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 整数类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 有符号整数:i8,i16,i32,i64,i128,isize</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 无符号整数:u8,u16,u32,u64,u128,usize</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// isize和usize类型依赖运行程序的计算机架构:64位计算机上是64位,32位计算机上是32位</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 默认是i32类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 除了byte类型,其他类型都可以用类型后缀来标注,例如123u32</span></span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 整数溢出</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// Rust在编译时会检查是否有整数溢出,如果有,会报错</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// debug模式下会panic,release模式下会wrap,例如256u8会变成0,257u8会变成1</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 例如:let x:u8 = 256;会报错</span></span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 浮点数类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// rust有两种浮点数类型:f32和f64</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 默认是f64类型</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">x</span> = <span class="number">2.0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">y</span>:<span class="type">f32</span> = <span class="number">3.0</span>;</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 数值操作</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 加法</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">sum</span> = <span class="number">5</span> + <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">difference</span> = <span class="number">95.5</span> - <span class="number">4.3</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">producy</span> = <span class="number">4</span> * <span class="number">30</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">quotient</span> = <span class="number">56.7</span> / <span class="number">32.2</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">reminder</span> = <span class="number">54</span> % <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 布尔类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// rust有两个布尔值:true和false</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 布尔类型的大小是1个字节</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 布尔类型的值是bool类型</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">t</span> = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">f</span>:<span class="type">bool</span> = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 字符类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// Rust的char类型是单个Unicode字符,可以表示比ASCII更多的字符,例如中文,日文,韩文等,甚至是emoji表情</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// Rust的char类型是4个字节</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// Rust的char类型用单引号表示</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// Unicode中没有字符的概念,只有代码点,代码点是一个数字,代表一个字符</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">x</span> = <span class="string">&#x27;z&#x27;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">y</span>:<span class="type">char</span> = &#x27;😻&#x27;;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">z</span> = <span class="string">&#x27;中&#x27;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;x的值是:&#123;&#125;&quot;</span>,x);</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;y的值是:&#123;&#125;&quot;</span>,y);</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;z的值是:&#123;&#125;&quot;</span>,z);</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 复合类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// Rust有两个复合类型:元组和数组</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 元组可以将多个不同类型的值组合在一起</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 数组可以将多个相同类型的值组合在一起</span></span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 元组tuple</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 元组是一个将多个其他类型的值组合在一起的复合类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 元组的长度是固定的,一旦声明,就不能增加或减少</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">tup</span>:(<span class="type">i32</span>,<span class="type">f64</span>,<span class="type">u8</span>) = (<span class="number">500</span>,<span class="number">6.4</span>,<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 获取tuple的值</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 可以使用模式匹配来解构一个tuple来获取元素的值</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> (x,y,z) = tup;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;x的值是:&#123;&#125;&quot;</span>,x);</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;y的值是:&#123;&#125;&quot;</span>,y);</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;z的值是:&#123;&#125;&quot;</span>,z);</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 访问tuple的元素</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 使用点号和索引来访问tuple的元素</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;&#123;&#125;,&#123;&#125;,&#123;&#125;&quot;</span>,tup.<span class="number">0</span>,tup.<span class="number">1</span>,tup.<span class="number">2</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 数组</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 数组是一个将多个相同类型的值组合在一起的复合类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 数组的长度是固定的,一旦声明,就不能增加或减少</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 数组的类型标注是[Type;size],例如:[i32;5]</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 数组的元素可以通过索引访问,索引从0开始</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">a</span> = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">b</span>:[<span class="type">char</span>;<span class="number">5</span>] = [<span class="string">&#x27;a&#x27;</span>,<span class="string">&#x27;b&#x27;</span>,<span class="string">&#x27;c&#x27;</span>,<span class="string">&#x27;d&#x27;</span>,<span class="string">&#x27;e&#x27;</span>];</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 如果想把数据存在stack(栈)上而不是heap(堆)上就可以使用数组</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 如果想保证有固定数量的元素,也可以使用数组</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 数组没有Vector灵活</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// Vector是可以改变长度的,数组是固定长度的</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">months</span> = [<span class="string">&quot;January&quot;</span>,<span class="string">&quot;February&quot;</span>,<span class="string">&quot;March&quot;</span>,<span class="string">&quot;April&quot;</span>,<span class="string">&quot;May&quot;</span>,<span class="string">&quot;June&quot;</span>,<span class="string">&quot;July&quot;</span>,<span class="string">&quot;August&quot;</span>,<span class="string">&quot;September&quot;</span>,<span class="string">&quot;October&quot;</span>,<span class="string">&quot;November&quot;</span>,<span class="string">&quot;December&quot;</span>];</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 这种不会变长度的就适合用数组</span></span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 如果每个元素都相同,还有一种语法</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">a</span> = [<span class="number">3</span>;<span class="number">5</span>];</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 这样就会生成一个包含5个3的数组</span></span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 访问数组元素</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 数组是栈上的单个块的内存</span></span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">first</span> = months[<span class="number">0</span>];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">second</span> = months[<span class="number">1</span>];</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;first的值是:&#123;&#125;&quot;</span>,first);</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;second的值是:&#123;&#125;&quot;</span>,second);</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 如果访问的索引超过了数组的范围,会报错panic</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// rust不允许其继续访问相应地址的内存,这样可以避免潜在的安全漏洞</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 不允许越界,只能访问数组占的内存空间</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 例如:let index = 10;let element = a[index];会报错</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 有时不会报错,例如:let index = [12,13,14,15]; let month = months[index[1]];可以通过编译,但是运行时会报错index out of bounds,程序panic</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">很好的命名法</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>Rust猜数游戏</title>
    <link href="https://mxts.jiujiuer.xyz/2024/04/17/%E7%8C%9C%E6%95%B0%E6%B8%B8%E6%88%8F/"/>
    <id>https://mxts.jiujiuer.xyz/2024/04/17/%E7%8C%9C%E6%95%B0%E6%B8%B8%E6%88%8F/</id>
    <published>2024-04-17T16:00:00.000Z</published>
    <updated>2026-05-28T06:52:01.719Z</updated>
    
    <content type="html"><![CDATA[<figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> std::io; <span class="comment">// prelude 序曲</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> rand::Rng; <span class="comment">// trait 是其他语言的接口,上面有很多方法</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> std::cmp::Ordering; <span class="comment">// 是一个枚举类型,有三个值,大于,小于,和等于</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// rust的库称为crate,crate是一个二进制或库,库是一个包含函数和其他代码的包,二进制crate是一个可以被执行的包,每个crate都有一个crate root,这是一个源文件,编译器从这个文件开始并编译整个crate,crate root是一个源文件,而不是一个目录,一个crate可以包含多个库,但只能包含一个二进制crate</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// crate分为二进制crate还有lib库,二进制crate是一个可以被执行的包,lib库是一个包含函数和其他代码的包,但不能被执行,只能被其他crate引用</span></span><br><span class="line"></span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;猜数!&quot;</span>);</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// rng是个接口,上面一个函数gen_range,范围是1-100,包括1,不包括101</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">secret_number</span> = rand::<span class="title function_ invoke__">thread_rng</span>().<span class="title function_ invoke__">gen_range</span>(<span class="number">1</span>..<span class="number">101</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// println!(&quot;神秘数字是:&#123;&#125;!&quot;, secret_number);</span></span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 使用loop循环,无限循环,直到猜对为止</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">loop</span>&#123;</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">        <span class="built_in">println!</span>(<span class="string">&quot;猜测一个数:&quot;</span>);</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">        <span class="comment">// let mut foo = 1;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// let bar = foo; // immutable</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 要表示0到100的范围,使用u32,无符号32位整数,默认是i32,有符号32位整数,也可以i64</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">guess</span> = <span class="type">String</span>::<span class="title function_ invoke__">new</span>();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 产生Stdin实例,存句柄,用read_line方法用可变的字符串参数获取输入,前面&amp;表示是引用传递参数,引用默认是不可变的,需要加入mut参数,readline返回Result类型变量,是枚举类型,值称为变体,两个变体:ok和err,ok变体包含一个元组,元组的第一个元素是一个引用,指向一个字符串,这个字符串是readline方法读取的内容,err变体包含一个错误值</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// Result上还定义了方法expect,如果是ok,则这个方法会提取里面的值,如果返回err,则expect会使程序崩溃,并显示传递给expect的参数,显示失败原因</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 不调用expect方法也行,但是会出现警告,安全性保证</span></span><br><span class="line"></span><br><span class="line">        io::<span class="title function_ invoke__">stdin</span>().<span class="title function_ invoke__">read_line</span>(&amp;<span class="keyword">mut</span> guess)</span><br><span class="line"></span><br><span class="line">            .<span class="title function_ invoke__">expect</span>(<span class="string">&quot;无法读取行&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// rust允许使用同名的新变量来隐藏之前的变量</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// trim方法去掉字符串前后的空白字符,parse方法将字符串转换为数字,parse方法返回Result类型,所以需要expect方法</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">let</span> <span class="variable">guess</span>:<span class="type">u32</span> = <span class="keyword">match</span> guess.<span class="title function_ invoke__">trim</span>().<span class="title function_ invoke__">parse</span>()&#123;</span><br><span class="line"></span><br><span class="line">            <span class="title function_ invoke__">Ok</span>(num) =&gt; num,</span><br><span class="line"></span><br><span class="line">            <span class="title function_ invoke__">Err</span>(_) =&gt; <span class="keyword">continue</span>,</span><br><span class="line"></span><br><span class="line">        &#125;;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// parse方法将字符串转换为数字,parse方法返回Result类型,所以需要expect方法</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 声明u32是为了告诉parse()方法,我们想要一个u32类型的数字,如果不声明,parse()方法会返回一个通用数字类型,这样就需要告诉编译器我们想要的类型</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 这之后的guess是一个新的变量,是一个u32类型,之前的guess是一个字符串类型</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 花括号是后面变量的值,用来在字符串中插入变量值</span></span><br><span class="line"></span><br><span class="line">        <span class="built_in">println!</span>(<span class="string">&quot;你猜测的数是: &#123;&#125;&quot;</span>, guess);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方法guess.cmp,compare,三种情况,使用一个枚举类型</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// match表达式,根据后面返回值决定做什么,多个手臂arm组成,每个手臂都有一个匹配的模式,匹配上就执行操作</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 如果match紧跟着的某个值和某个手臂的模式匹配,就会执行这个手臂的代码块</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 静态强类型语言</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">match</span> guess.<span class="title function_ invoke__">cmp</span>(&amp;secret_number)&#123;</span><br><span class="line"></span><br><span class="line">            Ordering::Less =&gt; <span class="built_in">println!</span>(<span class="string">&quot;太小了!&quot;</span>), <span class="comment">// arm</span></span><br><span class="line"></span><br><span class="line">            Ordering::Greater =&gt; <span class="built_in">println!</span>(<span class="string">&quot;太大了!&quot;</span>),</span><br><span class="line"></span><br><span class="line">            Ordering::Equal =&gt; &#123;</span><br><span class="line"></span><br><span class="line">                <span class="built_in">println!</span>(<span class="string">&quot;猜对啦!&quot;</span>);</span><br><span class="line"></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">            &#125;,</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">入门实践</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>矩阵分解与高斯消元</title>
    <link href="https://mxts.jiujiuer.xyz/2024/04/17/%E7%9B%B4%E6%8E%A5%E6%B3%95/"/>
    <id>https://mxts.jiujiuer.xyz/2024/04/17/%E7%9B%B4%E6%8E%A5%E6%B3%95/</id>
    <published>2024-04-17T16:00:00.000Z</published>
    <updated>2026-05-28T06:52:01.719Z</updated>
    
    <content type="html"><![CDATA[<p>我们之前就是消元法解方程嘛，先联立几个方程，然后把变量分离出来代入，最后得到一行只有一个变量的方程，把那个变量解出来，再重复上面的过程就可以了<br>但是计算机是不会干这件事的，这件事对于计算机来说，还是比较难的<br>我们要把这个问题变得简单一点，交给计算机去解决</p><hr><h1 id="三角形矩阵回代求解"><a href="#三角形矩阵回代求解" class="headerlink" title="三角形矩阵回代求解"></a>三角形矩阵回代求解</h1><h2 id="三角形矩阵"><a href="#三角形矩阵" class="headerlink" title="三角形矩阵"></a>三角形矩阵</h2><pre><code>什么样的方程组好解呢?</code></pre><p>直观地看, 三角形的方程组应该是好解的<br>$$\begin{cases}a_{11}x_1+a_{12}x_2+\cdots+a_{1n}x_n&#x3D;b_1\a_{22}x_2+\cdots+a_{2n}x_n&#x3D;b_2\\cdots\cdots\a_{nn}x_n&#x3D;b_n\end{cases}$$<br>像这个方程组, 我们只要从最下面一行开始解, 解出 $x_n$ 再往上代入就行了<br>重复上面的操作, 我们就可以解出所有的解<br>$$\begin{cases}&amp;x_n&#x3D;b_n&#x2F;a_{nn}\&amp;x_k&#x3D;\frac{b_k-\sum_{j&#x3D;k+1}^na_{kj}x_j}{a_{kk}}&amp;(k&#x3D;n-1,n-2,\cdots,1)\end{cases}$$</p><ul><li>这个过程称为回代过程</li><li>计算量为 $1+2+\cdots+n&#x3D;n(n+1)&#x2F;2$, 为平方级</li></ul><p>同理对下三角矩阵:<br>$$\begin{pmatrix}l_{11}\l_{21}&amp;l_{22}\\vdots&amp;\vdots&amp;\ddots\l_{n1}&amp;l_{n2}&amp;\cdots&amp;l_{nn}\end{pmatrix}\begin{pmatrix}x_1\x_2\\vdots\x_n\end{pmatrix}&#x3D;\begin{pmatrix}b_1\b_2\\vdots\b_n\end{pmatrix}$$<br>容易求得解:<br>$$\begin{aligned}&amp;x_1&#x3D;\frac{b_1}{l_{11}}\&amp;x_i&#x3D;\frac{b_i-\sum_{j&#x3D;1}^{i-1}l_{ij}x_j}{l_{ii}} i&#x3D;2,3,\cdots,n\end{aligned}$$</p><p>我们在[[高等代数]]中学习过, 通过相似变换, 线性方程组的解是不会变的<br>于是我们想到, 能不能通过相似变换, 把一个线性方程组 (矩阵) 变换成三角形的呢?<br>#符号 </p><ul><li>从此开始, 我们把解线性方程组同解矩阵等同起来</li></ul><hr><h2 id="如何将矩阵化为三角形"><a href="#如何将矩阵化为三角形" class="headerlink" title="如何将矩阵化为三角形"></a>如何将矩阵化为三角形</h2><p>把矩阵变成上&#x2F;下三角形, 我们主要有两种办法</p><ol><li>高斯消元法</li><li>非奇异矩阵三角分解</li></ol><hr><h1 id="高斯消元法与矩阵分解"><a href="#高斯消元法与矩阵分解" class="headerlink" title="高斯消元法与矩阵分解"></a>高斯消元法与矩阵分解</h1><p>我们一直在用的解线性方程组的办法, 叫做高斯消元法<br>[[高斯消元法例子]]<br>由上面的例子可以看出, 高斯消元法包括两个过程: <font color="#ff0000">消元</font>和<font color="#ff0000">回代</font><br>于是我们有如下方法</p><hr><h2 id="顺序高斯消元法"><a href="#顺序高斯消元法" class="headerlink" title="顺序高斯消元法"></a>顺序高斯消元法</h2><blockquote><p>[!note] 顺序高斯消元<br>考虑一个 $n$ 阶线性方程组<br>$$\begin{cases}a_{11}x_1+a_{12}x_2+…+a_{1n}x_n&#x3D;b_1\a_{21}x_1+a_{22}x_2+…+a_{2n}x_n&#x3D;b_2\\vdots\a_{n1}x_1+a_{n2}x_2+…+a_{nn}x_n&#x3D;b_n&amp;\end{cases}$$<br>把它化为矩阵形式:<br>$$Ax&#x3D;b$$<br>于是我们对矩阵进行操作<br>顺序高斯消元法的主要思路是, 把系数矩阵 $A$ 变成上三角矩阵, 然后回代求解<br>![[Pasted image 20240413233208.png|300]]<br>其实就是:<br>$$\begin{aligned}&amp;x_n&#x3D;b_n^{(n)}&#x2F;a_{nn}^{(n)}\&amp;x_i&#x3D;\left(b_i^{(i)}-\sum_{j&#x3D;i+1}^na_{ij}^{(i)}x_j\right)&#x2F;a_{ii}^{(i)}\end{aligned}$$</p></blockquote><ul><li>顺序高斯消元法硬性要求: 主元全都不为 $0$</li><li>主元即矩阵对角线上的元素: $a_{ii}^{(i)}\left(i&#x3D;1,2,…,n\right)$</li></ul><hr><h3 id="顺序高斯消元法的条件"><a href="#顺序高斯消元法的条件" class="headerlink" title="顺序高斯消元法的条件"></a>顺序高斯消元法的条件</h3><p>上面我们说过, 顺序高斯消元法要求主元 (对角元) 全都不为 $0$<br>这是因为我们的公式里有 $b_n^{(n)}&#x2F;a_{nn}^{(n)}$, 分母是不能为 $0$ 的</p><p>那么什么时候主元全都不为 $0$ 呢?<br>下面给出一个定理</p><blockquote><p>[!note] 主元不为 0 的充要条件<br>$a_{ii}^{(i)}\neq0(i&#x3D;1,\quad2,\cdots n)$, 的充要条件是 $A$ 的顺序主子式不为零，即<br>$$<br>D_1&#x3D;a_{11}\neq0,\quad D_i&#x3D;\begin{vmatrix}a_{11}&amp;\cdots&amp;a_{1i}\\vdots&amp;\ddots&amp;\vdots\a_{i1}&amp;\cdots&amp;a_{ii}\end{vmatrix}\neq0,\quad i&#x3D;1,2,…,n<br>$$</p></blockquote><hr><h3 id="具体操作"><a href="#具体操作" class="headerlink" title="具体操作"></a>具体操作</h3><p>[[顺序高斯消元法具体操作]]<br>对增广矩阵  $(\mathbf A,\mathbf b)$ 进行<strong>初等行变换</strong>，直到化成 <em>阶梯矩阵</em> ，然后回代计算出解</p><ul><li><strong>假设</strong>在消去过程中主对角元素始终不为 0<br>不断利用每行主对角元素消去下面同列的元素，逐渐使矩阵变成阶梯矩阵（上三角矩阵）<br>完成后回代<strong>求解</strong></li></ul><hr><h3 id="计算量"><a href="#计算量" class="headerlink" title="计算量"></a>计算量</h3><p>![[Pasted image 20240413234759.png|325]]</p><hr><h3 id="优缺点"><a href="#优缺点" class="headerlink" title="优缺点"></a>优缺点</h3><p>优点:</p><ul><li>计算量较小，结果准确</li><li>简单易行</li></ul><p>缺点:</p><ul><li>如果某个主元为 $0$, 就不能进行</li><li>如果某个主元很小, 精度会大大降低 ([[数值,误差与算法#避免小分母|小分母]]或者[[数值,误差与算法#避免大数吃小数|大数吃小数]])(也称为淹没)</li></ul><hr><h3 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h3><figure class="highlight matlab"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="params">[ X, U ]</span> = <span class="title">GaussElim</span><span class="params">( A, b )</span></span></span><br><span class="line">M = [A b];<span class="comment">%增广矩阵</span></span><br><span class="line">[n, ~] = <span class="built_in">size</span>(A);</span><br><span class="line">X = <span class="built_in">zeros</span>(n,<span class="number">1</span>);</span><br><span class="line"><span class="comment">%消去</span></span><br><span class="line"><span class="keyword">for</span> <span class="built_in">i</span> = <span class="number">1</span>:n<span class="number">-1</span></span><br><span class="line"><span class="comment">%消去</span></span><br><span class="line"><span class="keyword">for</span> <span class="built_in">j</span> = <span class="built_in">i</span>+<span class="number">1</span>:n</span><br><span class="line"><span class="comment">%计算得到乘子:m</span></span><br><span class="line">m = M(<span class="built_in">j</span>,<span class="built_in">i</span>)/M(<span class="built_in">i</span>,<span class="built_in">i</span>);</span><br><span class="line">M(<span class="built_in">j</span>,:) = M(<span class="built_in">j</span>,:)-m*M(<span class="built_in">i</span>,:);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">U = M(:,(<span class="number">1</span>:n));</span><br><span class="line"><span class="comment">%回代过程</span></span><br><span class="line">bn = M(:,n+<span class="number">1</span>);</span><br><span class="line">X(n) = bn(n)/M(n,n);</span><br><span class="line"><span class="keyword">for</span> k = <span class="number">1</span>:n<span class="number">-1</span></span><br><span class="line">X(n-k) = (bn(n-k)-M(n-k,(n-k+<span class="number">1</span>:n))*X(n-k+<span class="number">1</span>:n))/(n-k);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure><hr><h2 id="LU-分解-Doolittle"><a href="#LU-分解-Doolittle" class="headerlink" title="LU 分解(Doolittle)"></a>LU 分解(Doolittle)</h2><ul><li><p>也称为<strong>Doolittle</strong>分解<br>接下来我们将说明一个事实 ,就是顺序高斯消元法的消元过程等价于矩阵的 LU 分解<br>什么是 LU 分解? </p><blockquote><p>[!note] LU 分解<br>如果我们有一个矩阵 $A$, 把它分解为一个单位下三角矩阵 $L$ 和一个上三角矩阵 $U$<br>即$$A &#x3D; LU$$<br>这个过程称为矩阵 $A$ 的 $LU$ 分解</p></blockquote></li><li><p>$L$ 是一个<font color="#ff0000">单位</font>下三角矩阵, 它的对角线都是 $1$</p></li></ul><hr><h3 id="推导"><a href="#推导" class="headerlink" title="推导"></a>推导</h3><p>[[LU分解对应高斯消元法例子]]</p><hr><h3 id="LU-分解回代过程"><a href="#LU-分解回代过程" class="headerlink" title="LU 分解回代过程"></a>LU 分解回代过程</h3><p>既然我们把高斯消去法的消去步骤表示为 LU 分解, 那么如何转化回代步骤?<br>一旦知道 $L$ 和 $U$, 问题 $Ax &#x3D; b$ 就可以写成 $LUx&#x3D;b$, 我们定义辅助向量 $c&#x3D;Ux$<br>那么回代过程就变成了两步:</p><ol><li>对于方程 $Lc&#x3D;b$, 求解 $c.$ </li><li>对于方程 $Ux&#x3D;c:$, 求解 $x.$<br>由于 $L$ 和 $U$ 都是三角形的矩阵, 两步运算都很直接<br>例如:<br>$$\begin{bmatrix}1&amp;1\3&amp;-4\end{bmatrix}&#x3D;LU&#x3D;\begin{bmatrix}1&amp;0\3&amp;1\end{bmatrix}\begin{bmatrix}1&amp;1\0&amp;-7\end{bmatrix}$$<br>先进行步骤 1<br>$$\begin{bmatrix}1&amp;&amp;0\3&amp;&amp;1\end{bmatrix}\begin{bmatrix}c_1\c_2\end{bmatrix}&#x3D;\begin{bmatrix}3\2\end{bmatrix}$$<br>$$\begin{align}<br>c_1+0c_2&#x3D;3\3c_1+c_2&#x3D;2<br>\end{align}$$<br>解得 $c_{1}&#x3D;3,c_{2}&#x3D;-7$<br>再进行步骤 2<br>$$\begin{bmatrix}1&amp;&amp;1\0&amp;&amp;-7\end{bmatrix}\begin{bmatrix}x_1\x_2\end{bmatrix}&#x3D;\begin{bmatrix}&amp;3\-7\end{bmatrix}$$<br>$$\begin{aligned}x_1+x_2&amp;&#x3D;3\-7x_2&amp;&#x3D;-7\end{aligned}$$<br>解得 $x_{2}&#x3D;1,x_{1}&#x3D;2$</li></ol><hr><h3 id="LU-分解的条件"><a href="#LU-分解的条件" class="headerlink" title="LU 分解的条件"></a>LU 分解的条件</h3><p>我们上面说到, 矩阵的 $LU$ 分解是等价于顺序高斯消元法的, 这意味着两者的条件是相同的<br>$$<br>\text{LU分解存在} \Leftrightarrow \text{高斯消元法不中断} \Leftrightarrow a_{kk}^{(k)} \ne 0 \Leftrightarrow \text{所有顺序主子式不为}0<br>$$<br>参考[[直接法#顺序高斯消元法的条件|顺序高斯消元法的条件]]</p><hr><h3 id="计算量-1"><a href="#计算量-1" class="headerlink" title="计算量"></a>计算量</h3><p>计算量和顺序高斯消元法一致</p><hr><h3 id="优缺点-1"><a href="#优缺点-1" class="headerlink" title="优缺点"></a>优缺点</h3><ul><li>和高斯消元法基本一致, 但是, 如果等式的右边的项 $b$ 替换后,<br>$LU$ 分解不用重新进行计算, 相比高斯消元法更好</li><li>对于三对角或者对称正定线性方程组, $LU$ 分解更加高效</li></ul><hr><h3 id="代码-1"><a href="#代码-1" class="headerlink" title="代码"></a>代码</h3><figure class="highlight matlab"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="params">[ X,L, U ]</span> = <span class="title">GaussElimLU</span><span class="params">( A, b )</span></span></span><br><span class="line">M = [A b];<span class="comment">%增广矩阵</span></span><br><span class="line">[n, ~] = <span class="built_in">size</span>(A);</span><br><span class="line">X = <span class="built_in">zeros</span>(n,<span class="number">1</span>);</span><br><span class="line">L = <span class="built_in">eye</span>(n);</span><br><span class="line"><span class="comment">%消去</span></span><br><span class="line"><span class="keyword">for</span> <span class="built_in">i</span> = <span class="number">1</span>:n<span class="number">-1</span></span><br><span class="line"><span class="comment">%消去</span></span><br><span class="line"><span class="keyword">for</span> <span class="built_in">j</span> = <span class="built_in">i</span>+<span class="number">1</span>:n</span><br><span class="line"><span class="comment">%计算得到乘子:m</span></span><br><span class="line">LS = <span class="built_in">eye</span>(n);</span><br><span class="line">m = M(<span class="built_in">j</span>,<span class="built_in">i</span>)/M(<span class="built_in">i</span>,<span class="built_in">i</span>);</span><br><span class="line">M(<span class="built_in">j</span>,:) = M(<span class="built_in">j</span>,:)-m*M(<span class="built_in">i</span>,:);</span><br><span class="line">LS(<span class="built_in">j</span>,:) = LS(<span class="built_in">j</span>,:) - m*LS(<span class="built_in">i</span>,:);</span><br><span class="line">L = L*LS;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">U = M(:,(<span class="number">1</span>:n));</span><br><span class="line"><span class="comment">%回代过程</span></span><br><span class="line">bn = M(:,n+<span class="number">1</span>);</span><br><span class="line">X(n) = bn(n)/M(n,n);</span><br><span class="line"><span class="keyword">for</span> k = <span class="number">1</span>:n<span class="number">-1</span></span><br><span class="line">X(n-k) = (bn(n-k)-M(n-k,(n-k+<span class="number">1</span>:n))*X(n-k+<span class="number">1</span>:n))/(n-k);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure><hr><h2 id="列主元高斯消元法"><a href="#列主元高斯消元法" class="headerlink" title="列主元高斯消元法"></a>列主元高斯消元法</h2><p>之前的高斯消元法不是对主元要求很高吗, 既不能为 $0$ 也不能很小<br>我们就来挑一挑主元, 把大的数作为主元不就好了吗<br>我们知道, 把方程组的两行换一下, 方程组本质上是没有变的 (解也没有变)</p><blockquote><p>[!note] 列主元选取<br>在顺序高斯消元法的基础上作出改进:<br>再第 $k$ 步消元的时候, 我们在要消去的第 $k$ 个主元所在的行以及下面的行中选择<br>选出第 $k$ 个位置最大的行, 和我们现在这一行交换<br>(1) 先选取列主元：$|a_{i_kk}^{(k)}|&#x3D;\max_{k\leq i\leq n}\left{|a_{ik}^{(k)}|\right}\neq\mathbf{0}$<br>(2) 如果 $i_k\neq k$ 则交换第 $k$ 行和第 $i_k$ 行<br>(3) 消元</p><p>本质上, 我们可以这样看<br>我们先引入一个置换矩阵 $P$, 它的作用是对矩阵 $A$ 的行重新排一下序 (相当于提前换好行)<br>只要先用这个 $P$ 去乘矩阵 $A$, 接下来就做一般的顺序高斯消元法就好了<br>我们知道左乘相当于初等行变换<br>$$PA &#x3D; LU$$</p></blockquote><hr><h3 id="具体操作-1"><a href="#具体操作-1" class="headerlink" title="具体操作"></a>具体操作</h3><p>例如<br>$$<br>\begin{pmatrix}10^{-8}&amp;2&amp;3\-1&amp;3.712&amp;4.623\-2&amp;1.072&amp;5.643\end{pmatrix}\begin{pmatrix}x_1\x_2\x_3\end{pmatrix}&#x3D;\begin{pmatrix}1\2\3\end{pmatrix}<br>$$<br>此时我们处于 $k&#x3D;1$ 这一步, 于是从这行开始往下找, 可以发现第三行是最大的, 那就交换一三行</p><p>由于在消元的时候, 我们有<br>$$<br>a_{ij}&#x3D;a_{ij}-\frac{a_{ik}}{a_{kk}} \times a_{kj}<br>$$<br>但是我们这个 $a_{kk}$ 已经比下面的行($i&gt;k$)里的都要大了(本列最大), 可以保证 $\frac{a_{ik}}{a_{kk}}&lt;1$,<br>这意味着如果 $a_{kj}$ 有误差, 这个误差一定不会扩大, 是越来越小的 (乘以一个小于 1 的数)</p><ul><li>这样就保证了列主元高斯消元法的稳定性更好</li></ul><p>![[Pasted image 20240414000731.png|238]]</p><hr><h3 id="优缺点-2"><a href="#优缺点-2" class="headerlink" title="优缺点"></a>优缺点</h3><p>优点:</p><ul><li>主元有 $0$ 的时候也可以继续</li><li>当主元比较小的时候也不会放大误差</li></ul><p>缺点:</p><ul><li>要求 $\left| A \right| \ne 0$</li></ul><hr><h3 id="代码-2"><a href="#代码-2" class="headerlink" title="代码"></a>代码</h3><figure class="highlight matlab"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="params">[ X, U ]</span> = <span class="title">colGaussElim</span><span class="params">( A, b )</span></span></span><br><span class="line">M = [A b];<span class="comment">%增广矩阵</span></span><br><span class="line">[n, ~] = <span class="built_in">size</span>(A);</span><br><span class="line">X = <span class="built_in">zeros</span>(n,<span class="number">1</span>);</span><br><span class="line"><span class="comment">%消去</span></span><br><span class="line"><span class="keyword">for</span> <span class="built_in">i</span> = <span class="number">1</span>:n<span class="number">-1</span></span><br><span class="line"><span class="comment">%换主元</span></span><br><span class="line">N = <span class="built_in">abs</span>(M);</span><br><span class="line">[~, e] = <span class="built_in">max</span>(N((<span class="built_in">i</span>:n),<span class="built_in">i</span>));<span class="comment">%找出该列中主元绝对值最大的元素所在行的索引</span></span><br><span class="line">e=e+<span class="built_in">i</span><span class="number">-1</span>;</span><br><span class="line">temp = M(<span class="built_in">i</span>,:);</span><br><span class="line">M(<span class="built_in">i</span>,:) = M(e,:);</span><br><span class="line">M(e,:) = temp;<span class="comment">%替换结束</span></span><br><span class="line"><span class="keyword">if</span> M(<span class="built_in">i</span>,<span class="built_in">i</span>) == <span class="number">0</span></span><br><span class="line">error(<span class="string">&#x27;奇异阵&#x27;</span>);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="comment">%消去</span></span><br><span class="line"><span class="keyword">for</span> <span class="built_in">j</span> = <span class="built_in">i</span>+<span class="number">1</span>:n</span><br><span class="line"><span class="comment">%计算得到乘子:m</span></span><br><span class="line">m = M(<span class="built_in">j</span>,<span class="built_in">i</span>)/M(<span class="built_in">i</span>,<span class="built_in">i</span>);</span><br><span class="line">M(<span class="built_in">j</span>,:) = M(<span class="built_in">j</span>,:)-m*M(<span class="built_in">i</span>,:);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">U = M(:,(<span class="number">1</span>:n));</span><br><span class="line"><span class="comment">%回代过程</span></span><br><span class="line">bn = M(:,n+<span class="number">1</span>);</span><br><span class="line">X(n) = bn(n)/M(n,n);</span><br><span class="line"><span class="keyword">for</span> k = <span class="number">1</span>:n<span class="number">-1</span></span><br><span class="line">X(n-k) = (bn(n-k)-M(n-k,(n-k+<span class="number">1</span>:n))*X(n-k+<span class="number">1</span>:n))/(n-k);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure><hr><h2 id="PLU-分解"><a href="#PLU-分解" class="headerlink" title="PLU 分解"></a>PLU 分解</h2><p>和列主元高斯消元法的想法一样, 为了避免主元很小或者主元为 $0$ 时消元无法进行<br>我们对矩阵 $A$ 的行进行交换, 把大的数作为主元<br>这就需要我们引入一个置换矩阵 $P$, 提前对 $A$ 进行排序, 保证消元的精度</p><p>推导过程和 $LU$ 分解是类似的, 但是增加了一个记录行变换的步骤:</p><hr><h3 id="推导-1"><a href="#推导-1" class="headerlink" title="推导"></a>推导</h3><p>[[PLU分解推导]]</p><hr><h3 id="PLU-分解回代过程"><a href="#PLU-分解回代过程" class="headerlink" title="PLU 分解回代过程"></a>PLU 分解回代过程</h3><p>一旦知道 $L$ 和 $U$ 还有 $P$, 问题 $Ax &#x3D; b$ 就可以写成 $LUx&#x3D;Pb$, 我们定义辅助向量 $c&#x3D;Ux$<br>那么回代过程就变成了两步:</p><ol><li>对于方程 $Lc&#x3D;Pb$, 求解 $c.$ </li><li>对于方程 $Ux&#x3D;c:$, 求解 $x.$<br>由于 $L$ 和 $U$ 都是三角形的矩阵, 两步运算都很直接</li></ol><ul><li>注意这里左边的 $P$ 是隐含在 $LU$ 中的</li></ul><hr><h2 id="完全主元法"><a href="#完全主元法" class="headerlink" title="完全主元法"></a>完全主元法</h2><p>顾名思义, 就是在整个矩阵右下角找主元 (因为左上角已经变成对角的了)<br>如果是第一步, 那就是在整个矩阵里找主元</p><ul><li>相比列主元法, 其实就是在做列变换的同时, 也做行变换</li><li>在剩余矩阵中找最大的元素<blockquote><p>[!note] 完全主元<br>在列 高斯消元法的基础上作出改进:<br>再第 $k$ 步消元的时候, 我们在包括要消去的第 $k$ 个主元的右下角的矩阵中选择<br>选出最大的元素, 通过行列变换<br>(1) 先选取主元：$|a_{i_kj_k}^{(k)}|&#x3D;\max_{k\leq i\leq n,k\le j \le n}\left{|a_{ij}^{(k)}|\right}\neq\mathbf{0}$<br>(2) 如果 $i_k\neq k$ 或 $j_{k}\ne k$ 把 $a_{i_kj_k}$ 交换到 $a_{kk}$ 的位置<br>(3) 消元</p><p>本质上, 我们可以这样看<br>我们先引入两个置换矩阵 $P$ 和 $Q$, $P$ 的作用是对矩阵 $A$ 的行重新排一下序 (相当于提前换好行), $Q$ 的作用是对矩阵 $A$ 的列重新排一下序 (相当于提前换好列)<br>只要先用这个 $P$ 去左乘矩阵 $A$, 用这个 $Q$ 去右乘矩阵 $A$<br>我们知道左乘相当于初等行变换, 右乘相当于初等列变换<br>$$<br>PAQ &#x3D; LU<br>$$</p></blockquote></li></ul><p>假如这个矩阵里的所有元素中, 最大的三个元素为 $\lambda_1&gt;\lambda_2&gt;\lambda_3$<br>![[Pasted image 20240414004402.png]]<br>完全主元法实际上就是做了这样的事</p><hr><h3 id="代码-3"><a href="#代码-3" class="headerlink" title="代码"></a>代码</h3><figure class="highlight matlab"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="params">[P, Q, L, U]</span> = <span class="title">TotalGaussElim</span><span class="params">(A)</span></span></span><br><span class="line">[m, n] = <span class="built_in">size</span>(A);</span><br><span class="line"><span class="comment">% 初始化PQ</span></span><br><span class="line">P = <span class="built_in">eye</span>(m);</span><br><span class="line">Q = <span class="built_in">eye</span>(n);</span><br><span class="line"><span class="comment">% 初始化LU</span></span><br><span class="line">L = <span class="built_in">zeros</span>(m, m);</span><br><span class="line">U = <span class="built_in">zeros</span>(m, n);</span><br><span class="line"><span class="keyword">for</span> k = <span class="number">1</span>:<span class="built_in">min</span>(m<span class="number">-1</span>, n)</span><br><span class="line"><span class="comment">% 找到主元位置</span></span><br><span class="line">[~, pivot_row] = <span class="built_in">max</span>(<span class="built_in">abs</span>(A(k:m, k:n)));</span><br><span class="line">[~, pivot_col_idx] = <span class="built_in">max</span>(pivot_row);</span><br><span class="line">pivot_row = pivot_row(pivot_col_idx) + k - <span class="number">1</span>;</span><br><span class="line">pivot_col = pivot_col_idx + k - <span class="number">1</span>;</span><br><span class="line"><span class="comment">% 行列变换</span></span><br><span class="line"><span class="keyword">if</span> pivot_row ~= k</span><br><span class="line"><span class="comment">% 对A行变换</span></span><br><span class="line">temp = A(k, :);</span><br><span class="line">A(k, :) = A(pivot_row, :);</span><br><span class="line">A(pivot_row, :) = temp;</span><br><span class="line"><span class="comment">% 对P行变换</span></span><br><span class="line">temp = P(k, :);</span><br><span class="line">P(k, :) = P(pivot_row, :);</span><br><span class="line">P(pivot_row, :) = temp;</span><br><span class="line"><span class="comment">% 对L行变换</span></span><br><span class="line">temp = L(k, <span class="number">1</span>:k<span class="number">-1</span>);</span><br><span class="line">L(k, <span class="number">1</span>:k<span class="number">-1</span>) = L(pivot_row, <span class="number">1</span>:k<span class="number">-1</span>);</span><br><span class="line">L(pivot_row, <span class="number">1</span>:k<span class="number">-1</span>) = temp;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">if</span> pivot_col ~= k</span><br><span class="line"><span class="comment">% 对A列变换</span></span><br><span class="line">temp = A(:, k);</span><br><span class="line">A(:, k) = A(:, pivot_col);</span><br><span class="line">A(:, pivot_col) = temp;</span><br><span class="line"><span class="comment">% 对Q列变换</span></span><br><span class="line">temp = Q(:, k);</span><br><span class="line">Q(:, k) = Q(:, pivot_col);</span><br><span class="line">Q(:, pivot_col) = temp;</span><br><span class="line"><span class="comment">% 对U列变换</span></span><br><span class="line">temp = U(:, k);</span><br><span class="line">U(:, k) = U(:, pivot_col);</span><br><span class="line">U(:, pivot_col) = temp;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="comment">% 计算LU</span></span><br><span class="line">L(k:m, k) = A(k:m, k) / A(k, k);</span><br><span class="line">U(k, k:n) = A(k, k:n);</span><br><span class="line"><span class="comment">% 高斯消元</span></span><br><span class="line"><span class="keyword">for</span> <span class="built_in">i</span> = k+<span class="number">1</span>:m</span><br><span class="line">A(<span class="built_in">i</span>, k:n) = A(<span class="built_in">i</span>, k:n) - L(<span class="built_in">i</span>, k) * U(k, k:n);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="comment">% L的最后元素为1</span></span><br><span class="line">L(<span class="keyword">end</span>, <span class="keyword">end</span>) = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure><hr><h2 id="PQLU-分解"><a href="#PQLU-分解" class="headerlink" title="PQLU 分解"></a>PQLU 分解</h2><p>这个分解和完全主元法完全对应<br>$$<br>PAQ &#x3D; LU<br>$$<br>为了目录结构的完整性, 所以专门列为一个标题, 但是内容是和完全主元法一致的<br>相信看完前面 [[#推导|PLU分解]] 的推导, 这个也是很容易推出来的</p><hr><h2 id="追赶法-Crout"><a href="#追赶法-Crout" class="headerlink" title="追赶法 (Crout)"></a>追赶法 (Crout)</h2><ul><li>也称为<strong>Crout</strong>分解<br>对于系数矩阵三对角矩阵的线性方程组, 它的结构比一般的线性方程组简单很多<br>我们理应有更好的解法<blockquote><p>[!note] 三对角矩阵<br>形如以下矩阵为三对角矩阵:<br>$$\begin{bmatrix}\mathrm{a}<em>1&amp;\mathrm{c}<em>1\\mathrm{d}<em>2&amp;\mathrm{a}<em>2&amp;\mathrm{c}<em>2\&amp;\ddots&amp;\ddots&amp;\ddots\&amp;&amp;\mathrm{d}</em>{\mathrm{n}-1}&amp;\mathrm{a}</em>{\mathrm{n}-1}&amp;\mathrm{c}</em>{\mathrm{n}-1}\&amp;&amp;&amp;\mathrm{d}</em>{\mathrm{n}}&amp;\mathrm{a}</em>{\mathrm{n}}\end{bmatrix}\begin{bmatrix}\mathrm{x}<em>1\\mathrm{x}<em>2\\vdots\\mathrm{x}</em>{\mathrm{n}-1}\\mathrm{x}</em>{\mathrm{n}}\end{bmatrix}&#x3D;\begin{bmatrix}\mathrm{b}<em>1\\mathrm{b}<em>2\\vdots\\mathrm{b}</em>{\mathrm{n}-1}\\mathrm{b}</em>{\mathrm{n}}\end{bmatrix}$$</p></blockquote></li></ul><p>对于三对角矩阵, 如果它满足[[#追赶法的条件]], 就一定有如下分解:<br>$$<br>A&#x3D;LU<br>$$<br>其中<br>$$L&#x3D;\begin{bmatrix}l_{11}&amp;0&amp;…&amp;0\l_{21}&amp;l_{22}&amp;…&amp;0\\vdots&amp;\vdots&amp;\ddots&amp;\vdots\l_{n1}&amp;l_{n2}&amp;…&amp;l_{nn}\end{bmatrix},U&#x3D;\begin{bmatrix}1&amp;u_{21}&amp;…&amp;u_{n1}\0&amp;1&amp;…&amp;u_{n2}\\vdots&amp;\vdots&amp;\ddots&amp;\vdots\0&amp;0&amp;…&amp;1\end{bmatrix}$$</p><hr><h3 id="追赶法的条件"><a href="#追赶法的条件" class="headerlink" title="追赶法的条件"></a>追赶法的条件</h3><blockquote><p>[!note] 追赶法条件<br>若 $A$ 为<font color="#ff0000">对角占优</font>三对角阵，且满足<br>$|b_1|&gt;|c_1|&gt;0,|b_n|&gt;|a_n|&gt;0,\quad a_i\neq0,c_i\neq0$<br> $|b_{i}:|\ge|:a_{i}:|+|:c_{i}:|:,:a_{i}\cdot c_{i}\neq0\quad i&#x3D;2,\cdots,n-1$<br> 则方程组有唯一的 LU 分解<br> 对应的矩阵形式: $$<br>A&#x3D;LDM&#x3D;TM$$<br>其中 $T$ 是单位下三角矩阵, $M$ 是上三角矩阵<br>更彻底的分法其实是 $LDM$, 其中 $L$ 是单位下三角矩阵, $D$ 是对角矩阵, $M$ 是单位上三角矩阵</p></blockquote><ul><li>显然这个条件蕴含了三对角矩阵 A 的各阶顺序主子式都不为零</li></ul><hr><h3 id="具体操作-2"><a href="#具体操作-2" class="headerlink" title="具体操作"></a>具体操作</h3><p>操作起来是很简单的, 我找到一张很棒的图:<br>![[1ded1536454857.jpg]]<br>非常直观</p><hr><h2 id="平方根法-Cholesky-分解"><a href="#平方根法-Cholesky-分解" class="headerlink" title="平方根法(Cholesky 分解)"></a>平方根法(Cholesky 分解)</h2><p>对于三对角矩阵我们有很方便的解法, 那么对于对称正定矩阵又如何呢?<br>我们对于对称正定矩阵, 可以做 Cholesky 分解<br>先了解一下对称正定矩阵的特点:</p><blockquote><p>[!note] 对称正定矩阵性质<br>如果 $A$ 是一个对称正定矩阵, 那么:</p><ol><li>$A$ 的所有特征值 $&gt;0$</li><li>$A$ 是非奇异矩阵, 也就是各行各列线性无关, 行列式为 $\ne0$</li><li>$A^{-1}$ 也是对称正定的</li><li>$A$ 的对角线元素 (主元) $a_{ii}&gt;0\quad(i&#x3D;1,2,\cdots,n)$</li><li>$A$ 的所有顺序主子式均 $&gt;0$, 即 $\det(A_{k})&gt;0$</li></ol></blockquote><p>我们先来看看对称矩阵能分解成什么样</p><blockquote><p>[!note] 对称矩阵的三角分解<br>设 $A$ 是对称矩阵, 如果 $A$ 的所有顺序主子式都 $\ne0$, 那么 $A$ 有<strong>唯一</strong>的分解:<br>$$A&#x3D;LDL^{T}$$<br>其中 $L$ 为单位下三角矩阵, $D$ 为对角矩阵</p></blockquote><ul><li>直观地理解, 是很简单的, 其实就是消元:<br>我们通过 $L^{-1}$ 进行初等行变换消掉下三角部分, 由于这个矩阵是对称的<br>把 $L^{-1}$ 转置一下, 不就能消掉上三角部分了吗?<br>其实是 $L^{-1}A{L^{-1}}^T&#x3D;D$</li></ul><p>现在我们更进一步, 看看对称<strong>正定</strong>矩阵可以分解成什么样<br>我们已经可以得到 $A&#x3D;\tilde{L}D\tilde{L}^T$ (这里为了防止冲突, 我们把 $L$ 记为 $\tilde{L}$)<br>我们记 $D&#x3D;diag(d_1,d_2\cdots d_n)$ ($diag$ 指的是对角的意思), 由于 $A$ 是正定的<br>由性质 1, 我们可以把 $D$ 拆成两半<br>$$D^{\frac12}&#x3D;diag(\sqrt{d_1},\sqrt{d_2}\cdots\sqrt{d_n})$$<br>容易验证 $D^{\frac{1}{2}}\times D^\frac{1}{2}&#x3D;D$<br>又由于 $D^{\frac{1}{2}}&#x3D;{D^{\frac{1}{2}}}^T$, 我们可以得到:<br>$$<br>A&#x3D;\tilde{L}D^{\frac{1}{2}}{D^{\frac{1}{2}}}^T\tilde{L}^T&#x3D;\tilde{L}D^{\frac{1}{2}}({D^{\frac{1}{2}}}\tilde{L})^T<br>$$</p><p>如果我们记 $\tilde{L}D^{\frac{1}{2}}&#x3D;L$, 就得到:<br>$$<br>A&#x3D;LL^T<br>$$<br>这就是 $Cholesky$ 分解</p><blockquote><p>[!note] 对称正定矩阵的 Cholesky分解<br>若 $A$ 对称正定, 则 $A$ 可以唯一分解为<br>$$A&#x3D;LL^T$$<br>其中 $L$ 为实下三角矩阵, 对角元素均 $&gt;0$ </p></blockquote><hr><h3 id="具体操作-3"><a href="#具体操作-3" class="headerlink" title="具体操作"></a>具体操作</h3><p>![[Pasted image 20240414235714.png]]<br>如图所示, 只要把右侧矩阵乘起来, 一一对应位置来求解</p><ul><li>计算顺序：先求 $L$ 的第一列，即可知道 $L^T$ 的第一行，然后再求解 $L$ 的第二列，….，以此类推</li></ul><p>计算公式如下:<br>$$a_{ij}&#x3D;\sum_{k&#x3D;1}^nl_{ik}l_{jk}&#x3D;\sum_{k&#x3D;1}^{j-1}l_{ik}l_{jk}+l_{jj}l_{ij}$$<br>给出一个例子:<br>[[Cholesky分解例子]]</p><hr><h3 id="Cholesky-分解回代过程"><a href="#Cholesky-分解回代过程" class="headerlink" title="Cholesky 分解回代过程"></a>Cholesky 分解回代过程</h3><p>和上面类似<br>解方程：$Ly&#x3D;b$ 和 $L^Tx&#x3D;y$</p><hr><h3 id="优缺点-3"><a href="#优缺点-3" class="headerlink" title="优缺点"></a>优缺点</h3><p>优点:</p><ul><li>省内存:各值可以存放在原矩阵对应位置，不必开辟新的存储空间</li><li>不用选主元</li><li>具有数值稳定性</li><li>由于 $A$ 的对称性, 运算量为 $LU$ 分解的一半<br>缺点:</li><li>需要进行 $n$ 次开方运算, 而开放运算一定是有误差的, 还需要额外计算量</li></ul><hr><h2 id="改进的-Cholesky分解"><a href="#改进的-Cholesky分解" class="headerlink" title="改进的 Cholesky分解"></a>改进的 Cholesky分解</h2><p>运用平方根法计算量较大，为了避免开方运算，可以使用改进的 $Cholesky$分解</p><blockquote><p>[!note] 改进 Cholesky 分解<br>$A$ 为对称正定矩阵, 则我们改进的 $Cholesky$ 分解为:<br>$$A&#x3D;LDL^T$$<br>其中 $L$ 为单位下三角矩阵, $D$ 为对角矩阵</p></blockquote><p>说是改进, 其实这个是我们推出 $Cholesky$ 的中间产物, 之前已经见过了</p><hr><h3 id="具体操作-4"><a href="#具体操作-4" class="headerlink" title="具体操作"></a>具体操作</h3><p>$$A&#x3D;LDL^T&#x3D;\begin{bmatrix}1&amp;&amp;&amp;&amp;\l_{21}&amp;1&amp;&amp;&amp;\\vdots&amp;&amp;\ddots&amp;\l_{n1}&amp;\cdots&amp;l_{n,n-1}&amp;1\end{bmatrix}\begin{bmatrix}d_1&amp;&amp;&amp;\&amp;d_2&amp;&amp;\&amp;&amp;\ddots&amp;\&amp;&amp;&amp;d_n\end{bmatrix}\begin{bmatrix}1&amp;l_{21}&amp;\cdots&amp;l_{n1}\&amp;1&amp;&amp;l_{n2}\&amp;&amp;\ddots&amp;\vdots\&amp;&amp;&amp;1\end{bmatrix}$$<br>和上面的差不多, 我们把右边乘开, 对上位置列方程计算就行了<br>有计算公式:<br>$$a_{ij}&#x3D;\sum_{k&#x3D;1}^nl_{ik}d_kl_{jk}&#x3D;\sum_{k&#x3D;1}^{j-1}l_{ik}d_kl_{jk}+l_{ij}d_j$$</p><hr><h3 id="改进-Cholesky-分解的回代过程"><a href="#改进-Cholesky-分解的回代过程" class="headerlink" title="改进 Cholesky 分解的回代过程"></a>改进 Cholesky 分解的回代过程</h3><p>和前面类似, 就是求解 $Ly&#x3D;b$ 和 $DL^Tx&#x3D;y$</p><hr><h3 id="优缺点-4"><a href="#优缺点-4" class="headerlink" title="优缺点"></a>优缺点</h3><p>优点: 相比 Cholesky 分解不用进行开方运算</p><hr><p>下面已经没有了哦</p>]]></content>
    
    
    <summary type="html">矩阵分解解线性方程组</summary>
    
    
    
    
  </entry>
  
</feed>
