【数值计算】数值解析--n元一次联立方程组:直接解法
高斯消去法
加减法(中学所学)是我们平常用的解法之一。 例如,现有如下所示的二元一次方程组。
将等式两边同乘以一个实数,上下系数合并,消去其中一元未知数的方法便是熟知的加减法。
之后,把带入式1,解得。
把上式用行列式表示如下,
之后,第2行乘以,上下相减,得到
的形式。随后,从最下面的式子中解出未知数,代入,得到:
前面的操作是指,把系数行列的左下部分(不包括对角元素)全部变成0,求解如下所示的三角行列(upper triangle matrix)。
这样的处理称作前进消去(forward elimination)。 根据前进消去,未知数可通过解出, 把带入行可以解出,之后把 代入行可以解出 。然后反复执行类似的操作直到解出,这时我们便得到了所有解。这样的后半部分的处理称作后退代入(back substitution)。通过前进消去和后退代入求解n元1次方程组的方法便是高斯消去法。
高斯消去法的代码实现
首先,把常数向量添加到的最后一列组成的行列。
其中第i行j列的元素表示为
由于要在C,C++上实现,这里的元素序号从0开始计数。
前进消去可以表示成下式
这里的
根据上式,把用更新得到上三角行列。这一步的C++代码如下。
// 前进消去(forward elimination)// - 将左下角元素变为0
for(int k = 0; k < n-1; ++k){double akk = A[k][k];for(int i = k+1; i < n; ++i){double aik = A[i][k];for(int j = k+1; j < n+1; ++j){ A[i][j] = A[i][j]-aik*(A[k][j]/akk);}}
}
这里的二维数组A[n][n+1]中存储着系数行列和常数向量。
后退代入的公式如下。
C++代码:
// 后代入(back substitution)
// - x_n的解为b_n/a_nn,x_n,代入n-1行求出x_(n-1)A[n-1][n] = A[n-1][n]/A[n-1][n-1];
for(int i = n-2; i >= 0; --i){double ax = 0.0;for(int j = i+1; j < n; ++j){ax += A[i][j]*A[j][n];}A[i][n] = (A[i][n]-ax)/A[i][i];
}
计算结果存储于A[i][n]中。
高斯消去法的完整代码如下。
/*!* 高斯消去法(无主元交换)* @param[inout] A 为n×n的系数项与n×1的常数项(b)合并后n×(n+1)的行列* @param[in] n n元一次方程组* @return 1:成功*/
int GaussElimination(vector< vector<double> > &A, int n)
{// 前进消去(forward elimination)// - 左下角元素为0for(int k = 0; k < n-1; ++k){double akk = A[k][k];for(int i = k+1; i < n; ++i){double aik = A[i][k];for(int j = k+1; j < n+1; ++j){ A[i][j] = A[i][j]-aik*(A[k][j]/akk);}}}// 后退代入(back substitution)A[n-1][n] = A[n-1][n]/A[n-1][n-1];for(int i = n-2; i >= 0; --i){double ax = 0.0;for(int j = i+1; j < n; ++j){ax += A[i][j]*A[j][n];}A[i][n] = (A[i][n]-ax)/A[i][i];}return 1;
}
上面使用STL的vector代替2维数组。
主元选择
我们先重新看一遍高斯消去法中的前进消去公式。
会发现右侧的第二项中包含除以的计算。当前进消去过程中对角元素中有0时,则会停止计算。即使不为0,当有绝对值很小的数出现时也会有误差出现。
针对上述问题,这里我们对主元消元法(pivotal elimination method)进行说明。首先,我们知道联立方程的公式的顺序是可以交换的。也就是说,处理第行时,把其对角元素与同列还未处理的元素 的值进行比较,把绝对值最大的那一行与行互换后,应用到前进消去公式中。上述操作便是主元消元。 像这样的只交换行的操作称为部分主元消元(partial pivoting), 列方向也交换的操作称为完全主元消元(complete pivoting)。值得注意的是,部分主元消元中未知数的顺序不发生变化,完全主元消元中,未知数的顺序会发生变化。
包含主元消元的高斯消去法代码如下
/*!* 主元选择(Pivoting)* - 只交换行的部分主元消去法* @param[inout] A * @param[in] n n元一次方程组* @param[in] k 对象行* @return 1:成功*/
inline void Pivoting(vector< vector<double> > &A, int n, int k)
{// 检索k行后k列的绝对值最大元素所在行int p = k; // 绝对值最大的行double am = fabs(A[k][k]);// 最大値for(int i = k+1; i < n; ++i){if(fabs(A[i][k]) > am){p = i;am = fabs(A[i][k]);}}// 若k != p,行交换(主元选择)if(k != p) swap(A[k], A[p]);
}/*!* 高斯消去法(pivoting)* @param[inout] A * @param[in] n n元一次方程组* @return 1:成功*/
int GaussEliminationWithPivoting(vector< vector<double> > &A, int n)
{// 前进消去(forward elimination)for(int k = 0; k < n-1; ++k){// 主元消去Pivoting(A, n, k);double akk = A[k][k];for(int i = k+1; i < n; ++i){double aik = A[i][k];for(int j = k; j < n+1; ++j){A[i][j] = A[i][j]-aik*(A[k][j]/akk);}}}// 后退代入(back substitution)A[n-1][n] = A[n-1][n]/A[n-1][n-1];for(int i = n-2; i >= 0; --i){double ax = 0.0;for(int j = i+1; j < n; ++j){ax += A[i][j]*A[j][n];}A[i][n] = (A[i][n]-ax)/A[i][i];}return 1;
}
高斯・约当法
首先我们假设 是一个 的正方行列。 若 ,则是一个正则行列(regular matrix)(反之为奇异行列(singular matrix))。如果把 的单位行列表示成 ,且 非奇异,则只存在一个 行列 满足 。 这个可以用逆矩阵表示。
对于n元1次方程组,用替换,用替换。增广行列可以表示为
由于,两边同乘,得到
也就是说,增广行列的左侧一半变成了单位行列,右侧一半可以得到逆行列。
此时,逆行列为,
像这样的,扩增前进消去,执行上述处理求得逆行列的方法,便是高斯・约旦法。
高斯・约当法的实现
高斯・约当法公式如下。
求得逆行列代码如下
/*!* 高斯・约当法(无Pivoting)* @param[inout] A n×2n的增广行列* @param[in] n n元一次方程* @return 1:成功*/
int GaussJordan(vector< vector<double> > &A, int n)
{// 将增广行列的右半部分变为单位行列for(int i = 0; i < n; ++i){for(int j = 0; j < n; ++j){A[i][j+n] = (i == j ? 1.0 : 0.0);}}// 根据Gauss-Jordan method计算逆行列for(int k = 0; k < n; ++k){double akk = A[k][k];// 为使得对角元素为1,k行所有元素除以a_kkfor(int j = 0; j < 2*n; ++j){A[k][j] /= akk;}// k列的非对角元素变为0for(int i = 0; i < n; ++i){if(i == k) continue;double aik = A[i][k];for(int j = 0; j < 2*n; ++j){A[i][j] -= A[k][j]*aik;}}}return 1;
}
参考文献
- 佐藤次男, 中村理一郎, “よくわかる数値計算 アルゴリズムと誤差解析の実際”, 日刊工業新聞社, 2001.
- 川上一郎, “数値計算の基礎”, http://www7.ocn.ne.jp/~kawa1/
【数值计算】数值解析--n元一次联立方程组:直接解法相关推荐
- c语言如何就是联立方程组,准备出国读研的兄弟们:我们真的不如美国人勤奋---转自网络(转载)...
最痛苦的是第一次计量经济学作业.计量经济学是我们这里面最难的课,基本就是统计学在经济学中的应用,而且这门课是最近几十年才兴起的,国内教得很 浅.虽然我本科学了经济应用统计学,数理统计学,计量经济学,三 ...
- 双曲线和直线联立公式_高中圆锥曲线解题技巧之齐次化联立(四)
在开始介绍齐次化联立,我说过使用齐次化联立的题型特征,就是涉及两条直线的斜率和或者斜率积,并且这两条直线过同一个定点,其实还有一种题型也可以尝试使用齐次化联立,就是两直线夹角为定值问题,这个题型在全国 ...
- 双曲线和直线联立公式_谈直线和双曲线的位置关系之(1)联立方程法
[专题九]登峰造极,唯我独尊 --谈直线和双曲线的位置关系之(1)联立 方程法 直线与双曲线的位置关系题型包括①判断交点个数②判断相切.相交.相离三种位置关系③求弦长及三角形面积等问题:用到的思想是数 ...
- 【BZOJ3503】【Cqoi2014】和谐矩阵 高斯消元,解异或方程组
#include <stdio.h> int main() {puts("转载请注明出处");puts("地址:blog.csdn.net/vmurder/a ...
- Spark实施项目第七天-创建dw层订单明细表且与sku、spu、商标、类别进行联立
HBase中对四个维表进行建表 create table gmall_base_category3 ( id varchar primary key ,info.name varchar, info. ...
- 计算机多媒体技术视差估计,面向立体视频的视差_运动同步联立预测算法
<面向立体视频的视差_运动同步联立预测算法>由会员分享,可在线阅读,更多相关<面向立体视频的视差_运动同步联立预测算法(6页珍藏版)>请在技术文库上搜索. 1.第 22 卷第 ...
- Web项目实战 | 购物系统v2.0 | 开发记录(九)Controller层返回数据的封装 | 商品批量操作 | 五表联立实现商品搜索
--若发现文章内容有误,敬请指正,望不吝赐教,感谢! 文章目录 以往记录 运行环境 一.设计Bean用于Controller层返回数据 二.商品批量操作 2.1 批量操作的前端设计 2.2 批量操作的 ...
- Latex+WinDet联立公式编号及一行多图片写法
1.公式联立编号 实现代码 \begin{equation}%%编号\operatorname{ReLu}(\mathrm{x})=\left\{\begin{array}{ll}x & if ...
- fatfs文件系统与u盘驱动联立起来(usb_host)
1.FatFS是一个为小型嵌入式系统设计文件系统模块 正常移植系统后我们需要修改文件系统的两个.C文件ffconf.h和 diskio.c . ffconf.h 配置文件 修 ...
最新文章
- python与办公自动化-用 Python 自动化办公,我与大神之间的差距一下就拉小了
- asp.net 的page 基类页面 做一些判断 可以定义一个基类页面 继承Page类 然后重写OnPreLoad事件...
- 优化您的ApplicationContext
- smtplib 抄送邮件_用Python收发电子邮件
- java分治法求数列的最大子段和_同事为进大厂天天刷Java面试题,面试却履败!究其原因竟是它在捣鬼。...
- 头部导航菜单选中状态切换
- mysql 修改表属主_mysql主从配置实现一主一从读写分离
- 使用AdventNet快速开发网管软件Agent端
- 宋宝华:公元1024年Linux内核的尘封往事
- NC65新增按钮、新增按钮拦截器,某个字段制作超链接
- 秋招面经合集:阿里、华为、美团、携程、去哪儿、小米、京东都有
- Maya---基础知识总结
- PHP没有工作经验简历怎么写,没有工作经验应届生如何写简历呢?
- Springboot-banner图-定制化
- ES8218E低功耗24位ADC芯片 可直接接麦克风
- Android系统之ContentObserver和SettingsProvider结合使用(三)
- Java集合(一)Java集合及其关系
- 15款最佳的MySQL管理工具和应用程序
- 反应式架构:基本概念
- N位加减法运算器实现(Verilog HDL)|计算机组成