#include<iostream>
using namespace std;
#include<math.h>
void debug_print(float *c,int n);
bool ColPivot(float *,int,float *);
int main()
{
float *x = new float[3*sizeof(float)];
float c[3][4] ={10,-2,-1,3,
-2,10,-1,15,
-1,-2,5,10};
ColPivot(c[0],3,x);
for(int i=0;i<=2;i++ )
cout<<"x("<<i<<")="<<x[i]<<endl;
getchar();
return 0;
}
void debug_print(float *c,int n)
{
for(int i=0;i<n;i++)
{
for(int k=0;k<n+1;k++)
printf("%f ",*(c+i*(n+1)+k));
printf("\n");
}
printf("\n");
}
/**
* Gauss消去法是目前求解中小規模線性方程組(即階數不要太高,例如不超過1000)最常用的方法,
* 一般用于系數矩陣稠密(即矩陣的絕大多數元素都是非零的)而又沒有任何特殊結構的線性方程組。
* Gauss消去法實質上計算三角分解的方法。大緻可以分為兩步:消元和回代。
* 1、消元和回代的算法的實作
* 第一步:消元(将系數矩陣經過一系列的初等變換變成上三角矩陣),方法如下:
* 第二步:回代(依次解出X3、 X2 、X1)
* 2、每次對第K行之後的方程進行消元前要進行兩項操作:
* ① 檢查方程組第K到第N行方程中的第K列上元素是否為0,若是,則方程組無解或得不到為唯一解。
* ② 為了使方程組的解具有較小的計算誤差,必須使系數矩陣主對角線上的元素的絕對值為最大。
* 為此,在每消去第K行、第K列上主對角線元素以下的元素時,都要檢查一下主對角線上的元素
* 是否比其下的同列元素都大,若不是最大,則把最大元素所在行調換到第K行上(最大元素作為主對角線元素)
*/
bool ColPivot( float *c, int n, float *x )
{
for(int i=0;i<n-1;i++)
{
//根據2 ②判斷主對角線元素fabs是否最大
int col = i;
for(int j=i+1;j<n;j++)
{
if( fabs(*(c+j*(n+1)+i)) > fabs(*(c+col*(n+1)+i)) )
col = j;
}
//如果不是,進行行交換。注:包括常數向量
if(col!=i)
{
for(int k=i;k<n+1;k++)
{
float tmp = *(c+col*(n+1)+k);
*(c+col*(n+1)+k) = *(c+i*(n+1)+k);
*(c+i*(n+1)+k) = tmp;
}
}
//系數為0,無解或無窮多解。結束!
if(*(c+i*(n+1)+i) == 0)
return false;
//對剩餘行消元
for(int j=i+1;j<n;j++)
{
float p = *(c+j*(n+1)+i) / *(c+i*(n+1)+i);
for(int k=i;k<n+1;k++)
{
*(c+j*(n+1)+k) -= p * (*(c+i*(n+1)+k));
}
}
//debug_print(c,n);
}
//代入求解方程
for(int i=n-1;i>=0;i--)
{
for(int k=n-1;k>i;k--)
{
*(c+i*(n+1)+n) -= (*(c+i*(n+1)+k)) * x[k];
}
x[i] = *(c+i*(n+1)+n) / *(c+i*(n+1)+i);
}
return true;
}