计 算 方 法 实 验 报 告
动力与机械学院 08级自动化3班
唐禹
[1**********]78
2010.11.08
实验一 :使用列主元消去法求解线性方程组
列主元消去法是在Gauss消去法的基础上改进而得的一种比较快速和合理的求解线性方程组的方法。它的主要思路是通过对每次消元过程中主元的多次选取以达到减小误差和加快求解速度的一种消去法。使用列主元消去法相比于Gauss消去法基本上能控制舍入误差的影响,并且选主元素较全主元消去法更为方便。
其算法的设计思路如下:
该算法的具体流程图也如下图所示:
对应的C++程序源代码如下:
/*
编译环境 windows7 系统下 使用visual studio 2010 使用VC++6.0可能会用少许不兼容,修改一下即可 Copyright of 唐禹
Edited in 2010/11/01 Builed in 2010/11/01 Version 1.1 */
#include #include #include
using namespace std; int N; //方程的阶数,改用变量,可以由使用者决定方程阶数,程序更加灵活
double Main_Element; //记录每次选择的主元
double **A; double **B; double **A_B;
double **X;
/*用于试验的方程组 {3,1,6}; A= {2,1,3}; {1,1,1}; B= {2,7,4};
求的根为:X={19,-7,-8}; */ /*
为变量分配存储空间,初始化系数矩阵 */
void Init_Data(); /*
销毁变量空间 */
void Destroy_Data();
/*
求方程组Ax=B的增广矩阵A_B */
double** AUB(int N,double **A,double **B,double **A_B); /*
用于显示矩阵的详细参数,row x col型 */
void Show_Matrix(double **A,int row,int col); /*
用于横向显示向量,N x 1型 */
void Show_Result(int x/*表征解的个数/,int N);
int Gauss_Colum_Main_Element( int n, //方程阶数 double **A, //系数矩阵
double **B, //
double e);
//精度控制
/*
确定列主元素所在行,并返回行号 */
int Choose_Colum_Main_Element( int n, //方程阶数 double**A, //系数矩阵
int start);
/*
交换矩阵L1,L2两行 */
void Exchange(double **A,int num_of_colum,int L1,int L2); /*
单位化系数矩阵,更准确地说是将矩阵A的左上角nxn个分块矩阵单位化 */
double **Unitization(int n/*方程阶数*/,double**A /*系数矩阵*/);
/*
对确定好列主元素的矩阵进行消元处理 */
void Elimination(int n,double**A,int start);
/*主函数*/ int main() {
bool willgo; do {
Init_Data();
Show_Result(Gauss_Colum_Main_Element(N,A,B,0),N); cout
cin>>willgo; }while(willgo);
return 0;
}
//以下部分是对前面声明的函数的具体实现,相应的功能参看前面声明部分
//初始化数据
void Init_Data() { cout
while(N
cout
A=new double*[sizeof(double*)*N]; B=new double*[sizeof(double*)*1];
A_B=new double*[sizeof(double*)*(N+1)]; X=new double*[sizeof(double*)*1];
for(int i=0;i
A[i]=new double[N]; B[i]=new double[1];
A_B[i]=new double[N+1]; X[i]=new double[1]; }
cout
{
for(int j=0;j
cin>>A[i][j]; }
}
cout
cin>>B[i][0]; }
AUB(N,A,B,A_B);
}
//销毁数据
void Destroy_Data() {
for(int i=0;i
delete A[i]; delete B[i]; delete A_B[i]; delete X[i]; }
delete A; delete B; delete A_B; delete X; }
//求增广矩阵
double** AUB(int N,double **A,double **B,double **A_B) {
for(int i=0;i
for(int j=0;j
A_B[i][j]=A[i][j]; }
A_B[i][N]=B[i][0]; }
return A_B; }
//输出矩阵A的row x col 个元素
void Show_Matrix(double **A,int row,int col) {
cout
for(int i=0;i
cout
for(int j=0;j
cout
cout
cout
//输出最终结果
void Show_Result(double**X,int N) { if(x==0) // Gauss_Colum_Main_Element返回0,无解
{
cout
if(x==-1) // Gauss_Colum_Main_Element返回-1,为任意解
{
cout
cout
cout
cout
}
//高斯列主元消去法的主调函数
int Gauss_Colum_Main_Element( int N, //方程阶数 double **A, //系数矩阵
double**B, //
double e) //精度控制
{ cout
cout
int row=Choose_Colum_Main_Element(N,A_B,i); if(Main_Element
cout
Unitization(N,A_B);
cout
X[i][0]=A_B[i][N]; }
return 1;
A_0: //如果出现增广矩阵中|A|~0的情况处理如下 for(int i=0;i
if(abs(A_B[i][N])>e) return 0; }
//增广矩阵中|B|~0,即方程解为任意解的情况 return -1; }
//选取主元素,并返回主元所在的行
int Choose_Colum_Main_Element(int n,double**A,int start) {
int row=start;
double max=abs(A[start][start]); for(int i=start;i
if(max
{
row=i; max=A[i][start]; } }
Main_Element=max; return row;
}
//交换L1,L2行
void Exchange(double **A,int num_of_colum,int L1,int L2) {
double temp;
for(int i=0;i
temp=A[L1][i];
A[L1][i]=A[L2][i]; A[L2][i]=temp; } }
//消元过程函数(消元其实点为start,start)
void Elimination(int n,double**A,int start) {
double factor;
for(int i=start+1;i
factor=A[i][start]/A[start][start]; for(int j=start;j
A[i][j]=A[i][j]-factor*A[start][j]; } } }
//回带求解,即“单位化”增广矩阵
double **Unitization(int n,double**A) { double row_first; //行首元素 //主对角元素单位化
for(int i=0;i
row_first=A[i][i];
for(int j=0;j
{
A[i][j]=A[i][j]/row_first; } }
for(int k=n-1;k>0;k--) {
for(int i=0;i
double factor=A[i][k]; for(int j=0;j
A[i][j]=A[i][j]-factor*A[k][j]; } } }
return A;
}
关于本段程序的说明:
(1) 本程序对于方程组想系数矩阵不是采用默认的数组实现的,因为若采用数组实现则不能由使用者决定求解
方程的阶数,需要更改程序。故而此处采用二维指针的方式实现,这样程序很灵活,可以实现动态指定求解方程的阶数,但是同时也在一定程度上增加了程序的复杂程度。 (2) 关于“单位化”增广矩阵:其实这里A_B=[A B],并非NxN的矩阵,本没有单位化一说,这里为了便于
表述特将A_B经过转换所得形如[E B’]的过程,成为矩阵[A B]的单位化,其他的类推。 (3) 本程序最后的求解并不是采用书上面回带的方式求的最后的根的,而是采用“单位化”增广矩阵的方式来
实现的,其本质和回带是一样的,只是为了便于程序最后结果的输出。 (4) 另外,本程序版权归本人所有。
《程序的执行结果见下页》
下面是程序执行的结果记录:
请输入方程的阶数: 3
您选择了3阶方程组计算.
请输入系数矩阵A(按行输入): 注:为便于排版,执行的时候输入在一行中,并不影响程序结果
请输入系数矩阵A(按行输入): 1 0 0 1 0 0 0 0 1 请输入矩阵B: 0 0 0
Ax=B的增广矩阵为: 3 1 6 2 1 3 1 1 1 请输入矩阵B: 2 7 4
Ax=B的增广矩阵为:
| 3 1 6 2 | | 2 1 3 7 | | 1 1 1 4 |
解方程Ax=B的过程如下: 选取列主元后第1次消元:
| 3 1 6 2 | | 0 0.333333 -1 5.66667 || 0 0.666667 -1 3.33333 |
选取列主元后第2次消元:
| 3 1 6 2 | | 0 0.666667 -1 3.33333 || 0 0 -0.5 4 |
选取列主元后第3次消元:
| 3 1 6 2 | | 0 0.666667 -1 3.33333 | | 0 0 -0.5 4 |
单位化之后的结果:
| 1 0 0 19 | | 0 1 0 -7 | | -0 -0 1 -8 |
所求方程组的根为:(x1,x2,x3)=( 19 ,-7 ,-8 ). 退出(0)还是继续求解其他方程组(1)? 1
请输入方程的阶数: 3
您选择了3阶方程组计算.
| 1 0 0 0 | | 1 0 0 0 | | 0 0 1 0 |
解方程Ax=B的过程如下: 选取列主元后第1次消元:
| 1 0 0 0 | | 0 0 0 0 | | 0 0 1 0 |
方程组为任意解
退出(0)还是继续求解其他方程组(1)? 1
请输入方程的阶数: 3
您选择了3阶方程组计算.
请输入系数矩阵A(按行输入): 1 0 0 1 0 0 0 0 0 请输入矩阵B: 2 3 4
Ax=B的增广矩阵为:
| 1 0 0 2 | | 1 0 0 3 | | 0 0 0 4 |
解方程Ax=B的过程如下: 选取列主元后第1次消元:
| 1 0 0 2 | | 0 0 0 1 | | 0 0 0 4 |
由于消元过程中出现主元小于所设定的精度,且此时增广矩阵中B!~0 所以:方程无解
退出(0)还是继续求解其他方程组(1)? 0
计 算 方 法 实 验 报 告
动力与机械学院 08级自动化3班
唐禹
[1**********]78
2010.11.08
实验一 :使用列主元消去法求解线性方程组
列主元消去法是在Gauss消去法的基础上改进而得的一种比较快速和合理的求解线性方程组的方法。它的主要思路是通过对每次消元过程中主元的多次选取以达到减小误差和加快求解速度的一种消去法。使用列主元消去法相比于Gauss消去法基本上能控制舍入误差的影响,并且选主元素较全主元消去法更为方便。
其算法的设计思路如下:
该算法的具体流程图也如下图所示:
对应的C++程序源代码如下:
/*
编译环境 windows7 系统下 使用visual studio 2010 使用VC++6.0可能会用少许不兼容,修改一下即可 Copyright of 唐禹
Edited in 2010/11/01 Builed in 2010/11/01 Version 1.1 */
#include #include #include
using namespace std; int N; //方程的阶数,改用变量,可以由使用者决定方程阶数,程序更加灵活
double Main_Element; //记录每次选择的主元
double **A; double **B; double **A_B;
double **X;
/*用于试验的方程组 {3,1,6}; A= {2,1,3}; {1,1,1}; B= {2,7,4};
求的根为:X={19,-7,-8}; */ /*
为变量分配存储空间,初始化系数矩阵 */
void Init_Data(); /*
销毁变量空间 */
void Destroy_Data();
/*
求方程组Ax=B的增广矩阵A_B */
double** AUB(int N,double **A,double **B,double **A_B); /*
用于显示矩阵的详细参数,row x col型 */
void Show_Matrix(double **A,int row,int col); /*
用于横向显示向量,N x 1型 */
void Show_Result(int x/*表征解的个数/,int N);
int Gauss_Colum_Main_Element( int n, //方程阶数 double **A, //系数矩阵
double **B, //
double e);
//精度控制
/*
确定列主元素所在行,并返回行号 */
int Choose_Colum_Main_Element( int n, //方程阶数 double**A, //系数矩阵
int start);
/*
交换矩阵L1,L2两行 */
void Exchange(double **A,int num_of_colum,int L1,int L2); /*
单位化系数矩阵,更准确地说是将矩阵A的左上角nxn个分块矩阵单位化 */
double **Unitization(int n/*方程阶数*/,double**A /*系数矩阵*/);
/*
对确定好列主元素的矩阵进行消元处理 */
void Elimination(int n,double**A,int start);
/*主函数*/ int main() {
bool willgo; do {
Init_Data();
Show_Result(Gauss_Colum_Main_Element(N,A,B,0),N); cout
cin>>willgo; }while(willgo);
return 0;
}
//以下部分是对前面声明的函数的具体实现,相应的功能参看前面声明部分
//初始化数据
void Init_Data() { cout
while(N
cout
A=new double*[sizeof(double*)*N]; B=new double*[sizeof(double*)*1];
A_B=new double*[sizeof(double*)*(N+1)]; X=new double*[sizeof(double*)*1];
for(int i=0;i
A[i]=new double[N]; B[i]=new double[1];
A_B[i]=new double[N+1]; X[i]=new double[1]; }
cout
{
for(int j=0;j
cin>>A[i][j]; }
}
cout
cin>>B[i][0]; }
AUB(N,A,B,A_B);
}
//销毁数据
void Destroy_Data() {
for(int i=0;i
delete A[i]; delete B[i]; delete A_B[i]; delete X[i]; }
delete A; delete B; delete A_B; delete X; }
//求增广矩阵
double** AUB(int N,double **A,double **B,double **A_B) {
for(int i=0;i
for(int j=0;j
A_B[i][j]=A[i][j]; }
A_B[i][N]=B[i][0]; }
return A_B; }
//输出矩阵A的row x col 个元素
void Show_Matrix(double **A,int row,int col) {
cout
for(int i=0;i
cout
for(int j=0;j
cout
cout
cout
//输出最终结果
void Show_Result(double**X,int N) { if(x==0) // Gauss_Colum_Main_Element返回0,无解
{
cout
if(x==-1) // Gauss_Colum_Main_Element返回-1,为任意解
{
cout
cout
cout
cout
}
//高斯列主元消去法的主调函数
int Gauss_Colum_Main_Element( int N, //方程阶数 double **A, //系数矩阵
double**B, //
double e) //精度控制
{ cout
cout
int row=Choose_Colum_Main_Element(N,A_B,i); if(Main_Element
cout
Unitization(N,A_B);
cout
X[i][0]=A_B[i][N]; }
return 1;
A_0: //如果出现增广矩阵中|A|~0的情况处理如下 for(int i=0;i
if(abs(A_B[i][N])>e) return 0; }
//增广矩阵中|B|~0,即方程解为任意解的情况 return -1; }
//选取主元素,并返回主元所在的行
int Choose_Colum_Main_Element(int n,double**A,int start) {
int row=start;
double max=abs(A[start][start]); for(int i=start;i
if(max
{
row=i; max=A[i][start]; } }
Main_Element=max; return row;
}
//交换L1,L2行
void Exchange(double **A,int num_of_colum,int L1,int L2) {
double temp;
for(int i=0;i
temp=A[L1][i];
A[L1][i]=A[L2][i]; A[L2][i]=temp; } }
//消元过程函数(消元其实点为start,start)
void Elimination(int n,double**A,int start) {
double factor;
for(int i=start+1;i
factor=A[i][start]/A[start][start]; for(int j=start;j
A[i][j]=A[i][j]-factor*A[start][j]; } } }
//回带求解,即“单位化”增广矩阵
double **Unitization(int n,double**A) { double row_first; //行首元素 //主对角元素单位化
for(int i=0;i
row_first=A[i][i];
for(int j=0;j
{
A[i][j]=A[i][j]/row_first; } }
for(int k=n-1;k>0;k--) {
for(int i=0;i
double factor=A[i][k]; for(int j=0;j
A[i][j]=A[i][j]-factor*A[k][j]; } } }
return A;
}
关于本段程序的说明:
(1) 本程序对于方程组想系数矩阵不是采用默认的数组实现的,因为若采用数组实现则不能由使用者决定求解
方程的阶数,需要更改程序。故而此处采用二维指针的方式实现,这样程序很灵活,可以实现动态指定求解方程的阶数,但是同时也在一定程度上增加了程序的复杂程度。 (2) 关于“单位化”增广矩阵:其实这里A_B=[A B],并非NxN的矩阵,本没有单位化一说,这里为了便于
表述特将A_B经过转换所得形如[E B’]的过程,成为矩阵[A B]的单位化,其他的类推。 (3) 本程序最后的求解并不是采用书上面回带的方式求的最后的根的,而是采用“单位化”增广矩阵的方式来
实现的,其本质和回带是一样的,只是为了便于程序最后结果的输出。 (4) 另外,本程序版权归本人所有。
《程序的执行结果见下页》
下面是程序执行的结果记录:
请输入方程的阶数: 3
您选择了3阶方程组计算.
请输入系数矩阵A(按行输入): 注:为便于排版,执行的时候输入在一行中,并不影响程序结果
请输入系数矩阵A(按行输入): 1 0 0 1 0 0 0 0 1 请输入矩阵B: 0 0 0
Ax=B的增广矩阵为: 3 1 6 2 1 3 1 1 1 请输入矩阵B: 2 7 4
Ax=B的增广矩阵为:
| 3 1 6 2 | | 2 1 3 7 | | 1 1 1 4 |
解方程Ax=B的过程如下: 选取列主元后第1次消元:
| 3 1 6 2 | | 0 0.333333 -1 5.66667 || 0 0.666667 -1 3.33333 |
选取列主元后第2次消元:
| 3 1 6 2 | | 0 0.666667 -1 3.33333 || 0 0 -0.5 4 |
选取列主元后第3次消元:
| 3 1 6 2 | | 0 0.666667 -1 3.33333 | | 0 0 -0.5 4 |
单位化之后的结果:
| 1 0 0 19 | | 0 1 0 -7 | | -0 -0 1 -8 |
所求方程组的根为:(x1,x2,x3)=( 19 ,-7 ,-8 ). 退出(0)还是继续求解其他方程组(1)? 1
请输入方程的阶数: 3
您选择了3阶方程组计算.
| 1 0 0 0 | | 1 0 0 0 | | 0 0 1 0 |
解方程Ax=B的过程如下: 选取列主元后第1次消元:
| 1 0 0 0 | | 0 0 0 0 | | 0 0 1 0 |
方程组为任意解
退出(0)还是继续求解其他方程组(1)? 1
请输入方程的阶数: 3
您选择了3阶方程组计算.
请输入系数矩阵A(按行输入): 1 0 0 1 0 0 0 0 0 请输入矩阵B: 2 3 4
Ax=B的增广矩阵为:
| 1 0 0 2 | | 1 0 0 3 | | 0 0 0 4 |
解方程Ax=B的过程如下: 选取列主元后第1次消元:
| 1 0 0 2 | | 0 0 0 1 | | 0 0 0 4 |
由于消元过程中出现主元小于所设定的精度,且此时增广矩阵中B!~0 所以:方程无解
退出(0)还是继续求解其他方程组(1)? 0