Phương pháp khử toán phần ma trận
Bỏ qua nội dung
Giải hệ phương trình: Code: computational-physics/Gauss_Elimination_with_partial_pivoting.c Code: computational-physics/Gauss-Jordan_Elimination.c
Mình lược bỏ Interchange cho dễ nhìn. Bạn có thể thấy code khử Gauss và khử Jordan tương đồng nhau, chẳng qua chiều con chạy i, j chạy ngược nhau. Cách 2: Code: computational-physics/Synchronic_Gauss-Jordan_Elimination.c Chỉ sai khác một chút xíu mà nghiệm của 2 hệ hoàn toàn lệch nhau (bởi sau khi khử hàng, nó để lại số hạng cực bé, như mình trình bày vì sao có chèn thêm bước interchange trong thuật toán). Nếu như chuyện sai số từ dữ liệu đầu vào là ko thể tránh khỏi, vậy thì hãy chấp nhận sai số trong giới hạn bao nhiêu chữ số thập phân. Phương pháp lặp là phương pháp thử giá trị cho nghiệm, qua các bước lặp, các nghiệm giả định sẽ dần hội tụ về nghiệm chuẩn xác của hệ (dĩ nhiên trong phạm vi sai số bạn chọn). Tuy nhiên, phương pháp lặp chỉ hữu hiệu hơn phương pháp khử hàng khi xử lý các hệ có tính ổn định kém, chứ thực tình trong nhiều bài toán, phương pháp lặp còn “phế” hơn nhiều, bởi nó vướng phải một điểm yếu, đó là để đảm bảo sự hội tụ của nghiệm, hệ phải thoả mãn điều kiện tính chéo trội, tức là độ lớn của phần tử trên đường chéo chính phải lớn hơn độ lớn của các phần tử trong cùng hàng cộng lại. #include‹stdio.h› int main() { int n, i, j, k=0; printf("Nhap co he phuong trinh:\nn= "); scanf("%d",&n); double a[n][n+1]; printf("Nhap gia tri cho ma tran:\n"); for(i=0;i‹n;i++) { printf("Hang thu %d: ",i+1); for(j=0;j‹n+1;j++) scanf("%lf",&a[i][j]); } double x0[n], x[n], S, err=1e-9, delta; for(i=0;i‹n;i++) x0[i]=0; do { for(i=0;i‹n;i++) { S=0; for(j=0;j‹n;j++) if(j!=i) S+=a[i][j]*x0[j]; x[i]=(a[i][n]-S)/a[i][i]; } delta=0; for(i=0;i‹n;i++) { delta+=(x[i]-x0[i])*(x[i]-x0[i]); x0[i]=x[i]; } k++; } while(delta›err); printf("Nghiem he pt la:\n"); for(i=0;i‹n;i++) printf("x[%d]= %lf\n",i+1,x[i]); printf("Voi so buoc lap la k= %d\n",k); }Code: computational-physics/Jacobi_Iteration.c Code: computational-physics/Gauss-Seidel_Iteration.c Tìm ma trận nghịch đảo: Áp dụng phương pháp khử Gauss-Jordan để biến đổi ma trận dạng [A|I] thành dạng [I|B], khi đó B là ma trận nghịch đảo của A. Code: computational-physics/Inverse_Matrix.c Tính định thức: Như mình đã nói ở bài viết trong seri Đại số tuyến tính, ko ai đi dùng định nghĩa để tính định thức cả, mà biến đổi ma trận A thành ma trận tam giác trên U (mối quan hệ giữa định thức của 2 ma trận tuân theo tính chất 1, 2, 3 cũng đều nêu trong bài viết đó), và định thức của U bằng tích các phần tử đường chéo chính. #include‹stdio.h› #include‹math.h› int main() { int n, i, j, k, imax, sign=1; printf("Nhap co ma tran vuong n*n:\nn= "); scanf("%d",&n); double a[n][n], p; printf("Nhap gia tri cho ma tran:\n"); for(i=0;i‹n;i++) { printf("Hang thu %d: ",i+1); for(j=0;j‹n;j++) scanf("%lf",&a[i][j]); } for(k=0;k‹n-1;k++) { imax=k; for(i=k+1;i‹n;i++) if(fabs(a[i][k])›fabs(a[imax][k])) imax=i; if(imax!=k) sign*=-1; for(j=0;j‹n;j++) { p=a[k][j]; a[k][j]=a[imax][j]; a[imax][j]=p; } for(i=k+1;i‹n;i++) { p=a[i][k]/a[k][k]; for(j=k;j‹n;j++) a[i][j]-=p*a[k][j]; } } p=1; for(i=0;i‹n;i++) p*=a[i][i]; printf("Det= %.3lf\n",sign*p); }Code: computational-physics/Determinant.c |