天天看點

高斯(列)消去 C++實作

簡單的實作了一下數值計算課上的一個高斯消去求解多元方程的算法。代碼如下

#include<iostream>
#include<cmath>
using namespace std;
const int N=10;
const int N1=100;
double BMatrix[N];
 class Matrix{
	int size;//矩陣的大小
	double matrix[N1][N1];//增廣矩陣
	double solution[N1];//方程的解
public:
	Matrix(int k);//構造系數矩陣
	void disPlay();//顯示增廣矩陣
	void setAugmetMatrix(double *BMatrix);//生成增廣矩陣
	bool solveMatrix();//解矩陣,其中有消元和回代的過程
	int getSize();//擷取矩陣的大小
	double* getSolution();//獲得解的數組
	double* getFirstMatrix();//擷取矩陣第一行第一列元素
	int getMaxMainElement(int currentCol);//擷取最大主元所在的行
	void exchangTwoRow(int row1,int row2);//互動矩陣中的兩行
};
bool Matrix::solveMatrix(){
	for (int i = 1; i <= size; i++)//最外層循環周遊整個矩陣
	{
		if (getMaxMainElement(i)>0 &&i!=getMaxMainElement(i))
		{
			exchangTwoRow(getMaxMainElement(i),i);//交換行
		}
		cout<<"第"<<i<<"變換"<<endl;
		disPlay();
		cout<<endl;
		for (int j = i+1; j <= size; j++)//第二層循環周遊與上一層相鄰的層
		{
			double temp=matrix[j][i];//将在第k次消去的主元的第一個元素賦給temp臨時變量
			matrix[j][i]=0;//将第一進制素置0
			for (int k = i+1; k <=size+1; k++)//第三層循環周遊矩陣的列
			{
				matrix[j][k]=matrix[j][k]-(temp/matrix[i][i])*matrix[i][k];//根據矩陣消去公式依次肖元,成為上三角矩陣
			}
		}

	}  
	if (matrix[size][size]!=0)//預先判斷消去後的矩陣是否有确定解,然後進行回代
	{
		double temp;
		solution[1]=matrix[size][size+1]/matrix[size][size];//解得xn存入solution數組
		for (int i =2; i <=size; i++)
		{
			double A=matrix[size-i+1][size+1];//将bi賦給變量A
			for (int k = 1,j=1; k <i; j++,k++)
			{
				temp=A-solution[j]*matrix[size-i+1][size-k+1];//做減法
				A=temp;//指派使上面等式可連減
			}
			solution[i]=temp/matrix[size-i+1][size-i+1];//除以主對角線上的系數,得到xi
		}
		return true;
	}  

	return false;
}
Matrix::Matrix(int n){
	size=n;
	cout<<"請輸入方程的系數矩陣"<<endl;
	for(int i=1;i<=n;i++)
		for (int j = 1; j <=n; j++)
		{
			cin>>matrix[i][j];//錄入矩陣
		}
}
double* Matrix::getFirstMatrix(){
	double*p=& matrix[1][1];
	return p;
}
double* Matrix::getSolution(){
	return solution;
}
int Matrix::getSize(){
	return size;
}
void Matrix::disPlay(){
	for (int k = 1; k <= size; k++)
	{
		for (int m = 1; m <=size+1; m++)
		{
			if (m==size+1)
			{
				cout<<matrix[k][m]<<endl;//
			}
			else
			{
				cout<<matrix[k][m]<<"\t";
			}
		}
	}
}
void Matrix::setAugmetMatrix(double*BMatrix){
	for (int i = 1; i <=size; i++)
	{
		matrix[i][size+1]=BMatrix[i];//錄入常數列
	}
}
int Matrix::getMaxMainElement(int currentCol){
	double temp=0;
	int maxRowMain=0;
	for (int i = currentCol; i <= size; i++)
	{
		if (temp<matrix[i][currentCol])
		{
			temp=matrix[i][currentCol];
			maxRowMain=i;
		}
	}
	return maxRowMain;
}
void Matrix::exchangTwoRow(int row1,int row2){
	double tempMatrix=0;
	for (int i = 1; i <=size+1; i++)
	{
		tempMatrix=matrix[row1][i];
		matrix[row1][i]=matrix[row2][i];
		matrix[row2][i]=tempMatrix;
	}
}
int main()
{
	int n;
	cout<<"請輸入你方程系數矩陣的階"<<endl;
	std::cin>>n;
	Matrix m(n);
	double*p=m.getFirstMatrix();
	if (*p==0)
	{
		cout<<"第一行第一列元素不能為0"<<endl;
		return 0;
	}
	cout<<"請輸入常數項向量"<<endl;
	for (int i = 1; i <= n; i++)
	{
		cin>>BMatrix[i];
	}
	m.setAugmetMatrix(BMatrix);
	if(m.solveMatrix()){;
	/*m.disPlay();*///該方法有測試矩陣運算是否正确之用
	double* solute=m.getSolution();
	cout<<"方程的解為:"<<endl;
	for (int i =0; i < m.getSize(); i++)
	{
		cout<<"x"<<i+1<<"="<<solute[m.getSize()-i]<<endl;
	}
	}
	else
	{
		cout<<"此方程無解或無準确解。"<<endl;
	}
	return 0;
}
           

高斯消去比高斯列消去少了兩行代碼,即在每次消去時,選取列中最大元,并與此時用來消去其他行的行進行交換。

在列主消元中,找到列最大元,再與消去行互換,似的在消去過程中,不會因為除數過小,而造成計算結果産生較大誤差。高斯列消去法還是無法避免,在一些矩陣上出現由于,計算機本身精度,而造成資料的誤差,就我碰到的幾個矩陣,程式求解與手工求解,誤差在百分之五左右,四舍五入一下就是機器運算的結果。

程式運作樣例:

X1+X2-     4X4=1

-X1+X2+X3+3X4=-2

X1+3X2+5X3-4X4=-4

X2+2X3-X4=-2

可知矩陣為

1 1 0 -4

-1 1 1 3

1 3 5 -4

0 1 2 -1

常數項向量為

(1,-2,-4,-2)

高斯(列)消去 C++實作
高斯(列)消去 C++實作

繼續閱讀