接著上次的繼續,上次使用了高斯消元法http://blog.csdn.net/qq_26025363/article/details/53027926,但是,在消元過程中,無法使主要元素a(ii)≠0,但是很小時,用其做除數,會導致其他元素數量級的嚴重增長,舍入誤差的擴充,最後導致計算結果不可靠。所以這次採用列主要元素消去法來進行,思想就是將有小數的那行與該列中數最大的那行進行交換。
還是寫帖代碼吧
#include<iostream>#include<cmath>using namespace std;const int n = 3;//交換2個數的大小template<class T>void SWAP(T& a, T& b){ T c; c = a; a = b; b = c;}//高斯列主要元素消元法void gaussin_L(double a[n][n], double b[n]){ int i, j, k; int col, row; for (k = 0; k < n - 1; k++) { double ave = 0; //找出消元列中最大的那個元素所在的位置 for (i = k; i < n ; i++) if (fabs(a[i][k]) > ave) { ave = fabs(a[i][k]); cout << "ave " << ave << endl; row = i; col = k; } //如果該對角線元素是0,同樣不能用高斯消元法來求解 if (a[row][row] == 0) { cout << "can't solve" << endl; return; } //將找出的行進行交換 if (k != row) for (i = 0; i < n; i++) { SWAP(a[row][i], a[k][i]); SWAP(b[k], b[row]); } //消元過程 double c[n]; for (j = k + 1; j < n; j++) { c[j] = a[j][k] / a[k][k]; cout << c[j] << endl; } for (i = k + 1; i < n; i++) { for (j = 1; j < n; j++) { a[i][j] = a[i][j] - c[i] * a[k][j]; } b[i] = b[i] - c[i] * b[k]; } } double x[n]; x[n - 1] = b[n - 1] / a[n - 1][n - 1]; for (i = n - 2; i >= 0; i--) { double sum = 0; for (j = i + 1; j < n; j++) sum += a[i][j] * x[j]; x[i] = (b[i] - sum)/a[i][i]; } //列印輸出 for (i = 0; i < n ; i++) cout << " x" << "[" << i << "]=" << x[i] << endl;}`
對於該演算法,簡要的分析一下吧,該演算法基本還是沒有脫離高斯消元法,僅僅是稍微進行一個排序,減少了誤差,但是也增加了個排序的時間消耗,其他跟高斯消元法沒有區別,但是如果還想提高誤差精度之類的話,可以採用行列住元消去法,就是從整個矩陣中挑選出最大的那個數,作為除數,然後消元,接著挑第二次消元矩陣中最大的數進行消元。
==================================測試代碼`
int main(){double a[3][3] ={0.001,2.000,3.000,-1.000,3.712,4.623,-2.000,1.072,5.643};double b[3] = { 1.000,2.000,3.000 };gaussin_L(a, b);return 0;}
對於結果,其實誤差也不小,到小數點後4位左右就不準了,但是如果換其他的浮點數運算
對於結果,有時候誤差能把你嚇傻,這個方法還是不理想。如果對於這個大家有問題,歡迎多交流~