Giáo trình C - Chương 10: Giải hệ phương trình đại số tuyến tính
Giả sử ta có một hệ ph-ơng trình dạng số phức dạng AX = B trong đó A = C + jD , B
= E +jF và X = Y + jZ . Ta viết lại ph-ơng trình d-ới dạng :
(C + jD)(Y + jZ) = (E +jF) Nhân biểu thức về trái và cân bằng phần thựcvới phần thực và phần ảo với phần ảo ta
nhận đ-ợc hệ mới :
+ F = CZ DY
E = DZ - CY
Nh-vậy chúng ta nhận đ-ợc một hệ gồm 2n ph-ơng trình số thực . Giảihệ này và kết hợp
các phần thực à phần ảo ta nhận đ-ợc nghiệm của hệ ph-ơng trình ban đầu .
1x 06.101.02.12.03.1x 2.101.001.02.1x 1 3 1 2 1 1 1 2 2 2 3 2 1 2 01 106 01 0 948 0 9992 1 3 0 2 0 9992 01 0 948 100536 1 4 0 2 0 9992 0 2 100536 0 999098 x x x = − − = = − − = = − − = ⎧ ⎨ ⎪⎪⎪ ⎩ ⎪⎪⎪ ì ì ì ì ì ì , . . . . . , . . . . . , . . . . . và cứ thế tiếp tục . Ch−ơng trình mô tả thuật toán Gauss - Seidel nh− sau : 170 Ch−ơng trình 10-8 #include #include #include #include #include #define max 6 void main() { float b[max],x[max]; float a[max][max]; int i,j,k,n,dem,t1; float t,s,d,w,epsi; char tl; clrscr(); printf("Cho so an so n = "); scanf("%d",&n); printf("Cho cac phan tu cua ma tran a : \n"); for (i=1;i<=n;i++) for (j=1;j<=n;j++) { printf("a[%d][%d] = ",i,j); scanf("%f",&a[i][j]); } printf("\n"); printf("Ma tran a ma ban da nhap\n"); printf("\n"); for (i=1;i<=n;i++) { for (j=1;j<=n;j++) printf("%10.5f",a[i][j]); printf("\n"); } printf("\n"); t1=1; flushall(); while (t1) { printf("Co sua ma tran a khong(c/k)?"); scanf("%c",&tl); if (toupper(tl)=='C') { printf("Cho chi so hang can sua : "); scanf("%d",&i); printf("Cho chi so cot can sua : "); scanf("%d",&j); printf("a[%d][%d] = ",i,j); 171 scanf("%f",&a[i][j]); flushall(); } if (toupper(tl)=='K') t1=0; } printf("Ma tran a\n"); printf("\n"); for (i=1;i<=n;i++) { for (j=1;j<=n;j++) printf("%15.5f",a[i][j]); printf("\n"); } printf("\n"); printf("Cho cac phan tu cua ma tran b : \n"); for (i=1;i<=n;i++) { printf("b[%d] = ",i); scanf("%f",&b[i]); } printf("\n"); printf("Ma tran b"); printf("\n"); for (i=1;i<=n;i++) printf("b[%d] = %10.5f\n",i,b[i]); printf("\n"); t1=1; flushall(); while (t1) { printf("Co sua ma tran b khong(c/k)?"); scanf("%c",&tl); if (toupper(tl)=='C') { printf("Cho chi so hang can sua : "); scanf("%d",&i); printf("b[%d] = ",i); scanf("%f",&b[i]); flushall(); } if (toupper(tl)=='K') t1=0; } printf("\n"); printf("Ma tran b"); printf("\n"); for (i=1;i<=n;i++) printf("b[%d] = %10.5f\n",i,b[i]); printf("\n"); 172 printf("Cho so lan lap k : "); scanf("%d",&k); printf("\n"); w=1; epsi=1e-8; for (i=1;i<=n;i++) x[i]=0.0; dem = 0; do { dem=dem+1; for (i=1;i<=n;i++) { s=0.0; for (j=1;j<=n;j++) s=s+a[i][j]*x[j]; d=x[i]; x[i]=(1-w)*d+w*(-s+a[i][i]*d+b[i])/a[i][i]; t=fabs(d-x[i]); } } while ((demepsi*fabs(x[n]))); if (t<epsi*fabs(x[n])) { printf("Nghiem sau %d lan lap la :\n",dem); for (i=1;i<=n;i++) printf("x[%d] = %12.8f\n",i,x[i]); } else { printf("Khong dat do chinh xac sau %d lan lap\n",k); printf("Nghiem cua lan lap cuoi cung la : \n"); for (i=1;i<=n;i++) printf("x[%d] = %12.8f\n",i,x[i]); } getch(); } Đ7. Ph−ơng pháp Cramer Một tr−ờng hợp riêng của hệ ph−ơng trình , trong đó số ph−ơng trình bằng số ẩn , nghĩa là hệ có dạng : 11 1 12 2 13 3 1n 1 21 1 22 2 23 3 2 2 1 1 2 2 3 3 a x a x a x a x b a x a x a x a x b a x a x a x a x b n n n n n n nn n n + + + + = + + + + = + + + + = ⎧ ⎨ ⎪⎪⎪ ⎩ ⎪⎪⎪ ... ... ... ...... trong đó A= (aij) là một ma trận không suy biến . một hệ ph−ơng trình nh− vậy có tên là hệ thống Cramer 173 Định lí Crame : Hệ thống Crame có nghiệm duy nhất đ−ợc cho bởi công thức : i i x A A n= = ( ) (i ,..., )1 trong đó A(i) là ma trận nhận đ−ợc từ A bằng cách thay cột thứ i bởi cột B=[ b1 ,...,bn]T Nh− vậy để giải hệ bằng ph−ơng pháp Cramer chúng ta lần l−ợt tính các định thức của ma trận và ma trận thay thế rồi tìm nghiệm theo công thức Cramer. Ch−ơng trình sau mô tả thuật toán này, Ch−ơng trình 10-.9 // Cramer; #include #include #include #define max 50 void main() { float r[max][max],a[max][max]; float b[max],x[max]; float delta[max]; int i,j,k,l,t,n,ok1,ok2,t1; float c,d; char tl; clrscr(); printf("Cho so an cua phuong trinh n = "); scanf("%d",&n); printf("Cho cac phan tu cua ma tran a : \n"); for (i=1;i<=n;i++) for (j=1;j<=n;j++) { printf("a[%d][%d] = ",i,j); scanf("%f",&a[i][j]); } printf("\n"); printf("Ma tran a ma ban da nhap\n"); printf("\n"); for (i=1;i<=n;i++) { for (j=1;j<=n;j++) printf("%10.5f",a[i][j]); printf("\n"); } printf("\n"); t1=1; flushall(); while (t1) { 174 printf("Co sua ma tran a khong(c/k)?"); scanf("%c",&tl); if (toupper(tl)=='C') { printf("Cho chi so hang can sua : "); scanf("%d",&i); printf("Cho chi so cot can sua : "); scanf("%d",&j); printf("a[",i,",",j,"] = "); scanf("%f",&a[i][j]); flushall(); } if (toupper(tl)=='K') t1=0; } printf("Ma tran a \n"); printf("\n"); for (i=1;i<=n;i++) { for (j=1;j<=n;j++) printf("%10.5f",a[i][j]); printf("\n"); } printf("\n"); printf("Cho cac phan tu cua ma tran b : \n"); for (i=1;i<=n;i++) { printf("b[%d] = ",i); scanf("%f",&b[i]); } printf("\n"); printf("Ma tran b ma ban da nhap\n"); printf("\n"); for (i=1;i<=n;i++) printf("b[%d] = %10.5f\n",i,b[i]); printf("\n"); t1=1; flushall(); while (t1) { printf("Co sua ma tran b khong(c/k)?"); scanf("%c",&tl); if (toupper(tl)=='C') { printf("Cho chi so hang can sua : "); scanf("%d",&i); printf("b[%d] = ",i); scanf("%f",&b[i]); flushall(); } 175 if (toupper(tl)=='K') t1=0; } printf("\n"); printf("Ma tran b\n"); printf("\n"); for (i=1;i<=n;i++) printf("%10.5f",b[i]); printf("\n"); //thay b vao tung cot cua a de tinh cac dinh thuc for (k=0;k<=n;k++) { for (i=1;i<=n;i++) for (j=1;j<=n;j++)//thay cot b vao a if (i==k) r[j][i]=b[j]; else r[j][i]=a[j][i]; //tinh dinh thuc d=1.0; i=1; ok2=1; while (ok2&&(i<=n)) { if (r[i][i]==0.0) { ok1=1; t=t+1; while (ok1&&(t<=n)) if (r[t][i]!=0) { for (j=i;j<=n;j++) { c=r[i][j]; r[i][j]=r[t][j]; r[k][j]=c; } d=-d; ok1=0; } else t=t+1; if (k>n) { printf("\n"); printf("** MA TRAN SUY BIEN **"); ok2=0; d=0.0; } 176 } if (r[i][i]!=0) { c=r[i][i]; for (j=i+1;j<=n;j++) r[i][j]=r[i][j]/c; for (t=i+1;t<=n;t++) { c=r[t][i]; for (j=i+1;j<=n;j++) r[t][j]=r[t][j]-r[i][j]*c; } } i=i+1; } if (ok2) for (i=1;i<=n;i++) d=d*r[i][i]; delta[k]=d; } if (delta[0]==0.0) printf("He da cho vo nghiem\n"); else { printf("\nNGHIEM CUA HE :\n"); printf("\n"); for (i=1;i<=n;i++) { x[i]=delta[i]/delta[0]; printf("x[%d] = %10.5f\n",i,x[i]); } } getch(); } Đ8. Hệ ph−ơng trình số phức Giả sử ta có một hệ ph−ơng trình dạng số phức dạng AX = B trong đó A = C + jD , B = E +jF và X = Y + jZ . Ta viết lại ph−ơng trình d−ới dạng : (C + jD)(Y + jZ) = (E +jF) Nhân biểu thức về trái và cân bằng phần thực với phần thực và phần ảo với phần ảo ta nhận đ−ợc hệ mới : ⎩⎨ ⎧ + F = CZ DY E =DZ - CY Nh− vậy chúng ta nhận đ−ợc một hệ gồm 2n ph−ơng trình số thực . Giải hệ này và kết hợp các phần thực à phần ảo ta nhận đ−ợc nghiệm của hệ ph−ơng trình ban đầu . Ch−ơng trình giải hệ ph−ơng trình nh− vậy cho ở d−ới đây : 177 Ch−ơng trình 10-10 #include #include #include #include #include #define max 20 void main() { int i,j,k,l,n,m; float s,t,a[max][max],b[max][max],x[max]; clrscr(); printf("Cho so an so cua phuong trinh n = "); scanf("%d",&n); printf("Cho phan thuc cua cac he so,ke ca ve phai\n"); for (i=1;i<=n;i++) for (j=1;j<=n+1;j++) { printf("a[%d][%d] = ",i,j); scanf("%f",&a[i][j]); } printf("\n"); printf("Cho phan ao cua cac he so,ke ca ve phai\n"); for (i=1;i<=n;i++) for (j=1;j<=n+1;j++) { printf("b[%d][%d] = ",i,j); scanf("%f",&b[i][j]); } for (i=1;i<=n;i++) a[i][2*n+1]=a[i][n+1]; for (i=n+1;i<=2*n;i++) a[i][2*n+1]=b[i-n][n+1]; for (i=n+1;i<=2*n;i++) for (j=1;j<=n;j++) a[i][j]=b[i-n][j]; for (i=1;i<=n;i++) for (j=n+1;j<=2*n;j++) a[i][j]=-b[i][j-n]; for (i=n+1;i<=2*n;i++) for (j=n+1;j<=2*n;j++) a[i][j]=a[i-n][j-n]; m=2*n; for (k=1;k<=m-1;k++) { s=0.0; 178 for (i=k;i<=m;i++) { t=fabs(a[i][k]); if (s<=t) { s=t; l=i; } } for (j=k;j<=m+1;j++) { s=a[k][j]; a[k][j]=a[l][j]; a[l][j]=s; } if (fabs(a[k][k]/a[1][1])<=1e-08) { printf("Ma tran suy bien\n"); getch(); exit(1); } for (i=k+1;i<=m;i++) { s=a[i][k]/a[k][k]; a[i][k]=0.0; for (j=k+1;j<=m+1;j++) a[i][j]-=s*a[k][j]; } } x[m]=a[m][m+1]/a[m][m]; for (i=m-1;i>=1;i--) { s=a[i][m+1]; for (j=i+1;j<=m;j++) s-=a[i][j]*x[j]; x[i]=s/a[i][i]; } printf("\n"); printf("Nghiem phuc cua he\n"); for (i=1;i<=n;i++) if (x[i+n]<0) printf("%10.5f-%10.5fj\n",x[i],fabs(x[i+n])); else printf("%10.5f+%10.5fj\n",x[i],x[i+n]); getch(); } Dùng ch−ơng trình này giải hệ ph−ơng trình : 179 ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 3 7 2 4 1 3 4 2 8 36 5 6 2 5 3 4 10 4 5 1 2 5 6 13 3 2 4 1 2 3 10 6 + + − + + − + + = + − + + + − + = + + + + + − − + = − + + − + − = − + ⎧ ⎨ ⎪⎪ ⎩ ⎪⎪ j x j y j z j r j j x j z j r j j x j y j z r j j x j y j r j Ta nhận đ−ợc các nghiệm x = 2 + 3j ; y = 1 - 2j ; z = -1 + 4j và r = 1- j Ngoài các ph−ơng pháp nêu trên ta thấy rằng từ hệ ph−ơng trình AX = B ta có thể tìm nghiệm X của hệ bằng cách viết lại ph−ơng trình d−ới dạng X = B/A =A-1B với A-1 là ma trận nghịch đảo của A . Do vậy tr−ớc hết ta cần tìm A-1 và sau đó tính tích A-1B.
File đính kèm:
- Giao_Trinh_C_Chuong10_CachgiaihePT.pdf