矩陣分解 三角分解(LU分解) - billbliss的專欄 - CSDN博客 https://blog.csdn.net/billbliss/article/details/78559289
矩陣的三角分解其基本原理可見上面的博客鏈接(寫的很好,此處不再贅述)。
本博客主要是給出三角分解的C語言實現過程。
這裏舉出的計算實例如下所示:
=
1. 我們採用的第一種方法是,給L矩陣和U矩陣在main函數中進行初始化。然後傳入到子函數中進行賦值。
/*我們在這裏來創建一個函數,來實現三角分解法
以下函數的參數中,所有名爲: Arr是方程組的稀釋矩陣
L是存儲三角分解的下三角矩陣的內存空間
U是存儲三角分解的上三角矩陣的內存空間
N 是矩陣的階數 */
void Triangle_decomp(double (*Arr)[3], double (*L)[3], double (*U)[3], int N){
// 對於三角分解的方式是進行先是行的賦值,然後是列的賦值
// 首先要記得L是單位下三角矩陣,U是上三角矩陣
// 對於三角分解的方式是先行後列,也就是說需要先確定U的一行,然後才能確定L的一列
// 首先對於U的第一行可以直接賦值
for(int i=0; i<N; i++) U[0][i] = Arr[0][i];
// 然後接下來我們需要先給L中的第一列進行賦值
for(int i=0; i<N; i++){
L[i][i] = 1;
L[i][0] = Arr[i][0] / Arr[0][0];
}
// 接下來我們來進行後面數組的賦值
double sum_val = 0.0;
for(int i=1; i<N; i++){
// 然後來進行U的行的賦值.
// 我們的求和是對應U的上面的所有的行
// 我們這裏需要遍歷上面的行,並求和
for(int d=i; d<N; d++){
sum_val = 0.0;
// 這裏遍歷的d是對應的列上的索引,但是對應的d的起始索引應該是什麼呢???
for(int row_i=i-1; row_i>=0; row_i--){
sum_val += L[i][row_i] * U[row_i][d];
}
// 然後我們來得到對應的L上的元素
U[i][d] = Arr[i][d] - sum_val;
}
// 當跳出循環後,便完成了U的行的賦值
// 當進行L的賦值之後,對應的遍歷i變成了對應的列索引
for(int row_i=i+1; row_i<N; row_i++){
// 這裏的循環是對應的L中的行,接下來該怎麼做?
sum_val = 0.0;
for(int d=i-1; d>=0; d--){ // 這裏的d是對應的列索引
sum_val += L[row_i][d] * U[d][i];
}
L[row_i][i] = (Arr[row_i][i] - sum_val) / U[i][i];
}
}
}
運算結果如下圖:
2. 我們採用的第二種方法是直接將L中的元素和U中的元素寫入到Arr矩陣中去.
/*接下來我們來創建一個方法,來計算生成新的Arr數組*/
void Triangle_decomp01(double (*Arr)[3], int N){
// 本方法是爲了實現將係數矩陣中的具體內容寫入到原係數矩陣中去
// 首先第一行不去變化,因爲原L中的對角線上元素將不再出現
// 接下來處理第一列,對於第一列元素,
for(int i=1; i<N; i++) Arr[i][0] /= Arr[0][0];
double sum_val = 0.0;
// 接下來該是先去處理行上的元素,然後再去處理列上的元素
for(int i=1; i<N; i++){
// 接下來首先需要進行列上元素的遍歷,對於列上元素的起始索引,應該是當前的行數
for(int col_i=i; col_i<N; col_i++){
sum_val = 0.0;
// 接下來進行求和計算,求和是當前行以上的所有的行
for(int d=i-1; d>=0; d--){
sum_val += Arr[i][d] * Arr[d][col_i];
}
// 接下來來計算對應的U上的元素
// 對於U上對應位置上的元素,我們只需要將原索引上的值減去sum_val即可
Arr[i][col_i] -= sum_val;
}
// 接下來我們需要做的便是來處理L的列上的元素
// 當我們來遍歷列上的元素時,對應的i將會轉爲遍歷的列上
for(int row_i=i+1; row_i<N; row_i++){ // 接下來首先需要遍歷的便是行
// 接下來該是來進行求和了
sum_val = 0.0;
for(int col_i=i-1; col_i>=0; col_i--){
// 這裏遍歷的col_i 是在L中對應的列
sum_val += Arr[row_i][col_i] * Arr[col_i][i];
}
Arr[row_i][i] = (Arr[row_i][i]-sum_val) / Arr[i][i];
}
}
}
運算結果見下圖:
3. 我們採用的第三種方式是,將係數矩陣寫爲1D,並將L中的數據和U中的數據覆蓋到原Arr中去。
/*接下來創建一個方法,該方法將採用1D的係數矩陣來進行方程組的求解*/
void Triangle_decomp02(double *Arr, int N){
// 第一行中的所有元素將不會再改變,
// 我們要做的是先來處理第一列上的元素
for(int i=1; i<N; i++){
// 這裏的遍歷是第一列上的索引
Arr[i*N+0] = Arr[i*N+0] / Arr[0];
}
// 接下來我們要做的便是該去進行後續的行的數據操作了
// 首先遍歷的是當前要處理的行
double sum_val = 0.0;
for(int i=1; i<N; i++){
// 內部的循環應該首先是列,因爲已經制定了要處理的行
// 接下來需要首先指定我們要處理的列
for(int col_i=i; col_i<N; col_i++){
// 因爲這裏的U是從主元按照行的順序向後進行處理
// 接下來便是求和的數據了, 求和是按照行向上進行的
sum_val = 0.0;
for(int d=i-1; d>=0; d--){
// 內部的求和,必須是所操作行上面的所有行
// sum_val += Arr[i][d]*Arr[d][col_i];
sum_val += Arr[i*N+d] * Arr[d*N+col_i];
}
// Arr[i][col_i] -= sum_val;
Arr[i*N+col_i] -= sum_val;
}
// 接下來我們該來處理L中對應的列上的元素了
// 此處i將自動轉爲L中的列索引
// 那麼下面我們首先應該去進行行的遍歷了
for(int row_i=i+1; row_i<N; row_i++){
// 接下來需要進行遍歷求和了,當然遍歷的是當前列的前面的所有列
sum_val = 0.0;
for(int col_i=i-1; col_i>=0; col_i--){
// sum_val += Arr[row_i][col_i] * Arr[col_i][i];
sum_val += Arr[row_i*N+col_i] * Arr[col_i*N+i];
}
// Arr[row_i][i] = (Arr[row_i][i] - sum_val) / Arr[i][i];
Arr[row_i*N+i] = (Arr[row_i*N+i] - sum_val) / Arr[i*N+i];
}
}
}
運算結果見下圖:
程序有什麼問題,請留言,相互討論共同進步。千萬不要停下學習的腳步,社會競爭壓力很大。從學校出來以後,感覺錢真是太難掙了,尤其房價高的嚇人。估計等我攢夠買房子的錢的時候,我已經250歲了。
龍豬是個貧苦大戶,當前支持以下扶貧方式。