Các phép toán thực hiện trên ma trận thực
Trang 1
CHƯƠNG I : ĐẶT VẤN ĐỀ
I MỤC ĐÍCH CỦA ĐỢT THỰC TẬP
Qua đợt thực tập này sẽ tạo điều kiện để sinh viên nghiên cứu sâu hơn
về một số vấn đề được giới thiệu trên lớp học.Qua đó nâng cao khả năng sử dụng ngôn ngữ lập trình,làm quen dần với việc giải quyết các bài toán ứng dụng
II ĐỀ TÀI THỰC TẬP
1 Tên đề tài : Các phép toán thực hiện trên ma trận thực
2 Nội dung và yêu cầu của đề tài :
Nội dung :
Xây dựng chương trình thực hiện các phép toán trên ma trận thực: cộng ,trừ,nhân hai ma trận : tính định thức ma trận vuông bằng cách dùng công thức hoán vị,từ đó tìm hạng của ma trận vuông C
III CÁC NHIỆM VỤ CỤ THỂ ĐẶT RA TRONG ĐỀ TÀI
Ngoài các nội dung chính thực hiện trên ma trận thực :cộng ,trừ ,nhânhai ma trận,tính định thức ma trận vuông dùng công thức hoán vị và tìm hạng của ma trận vuông ,để giải quyết đề tài một cách trọn vẹn ta còn phải tạo dữ
liệu vào cho chương trình thông qua file văn bản và tạo giao diện(menu) cho
chương trình Như vậy với đề tài này thì các nhiệm vụ đặt ra là :
1 Tạo dữ liệu đầu vào ( Tạo file lưu trữ các thông tin về ma trận)
2 Thực hiện các phép toán trên ma trận thực :
Cộng hai ma trận
Trang 2 Trừ hai ma trận
Tích hai ma trận
Tính định thức của ma trận vuông
Tính hạng của ma trận vuông
3 Tạo giao diện cho chương trình
CHƯƠNG II : XÂY DỰNG CHƯƠNG TRÌNH
Trang 3Với mục đích và yêu cầu của bài toán trong đề tài thì chương trình sẽ thực hiện các công việc như sau :
Thực hiện các phép toán trên ma trận thực
Tính định thức của ma trận vuông bằng cách dùng công thức hoán vị,từ đó tìm hạng của ma trận
Tuy nhiên để hoàn thiện đề tài thì ta phải tạo đươc các ma trận bất kỳ và
ma trận vuông Nhưng để tạo được ma trận thì ta cần phải nhập vào số liệu
do vậy ta phải thêm bước tạo file để sử dụng trong chương trình Hơn nữa sau khi tạo ma trận và thực hiện các phép toán trên ma trận thì để tiện sử dụng và kiểm tra thì ta cần ghi chúng vào các file sau đó tiến hành đọc chúngkhi có yêu cầu
Như vậy khi thực hiện chương trình thì gồm các bước chính sau :
Tạo ma trận từ file và từ bàn phím
Thực hiện các phép toán trên ma trận thực và ghi vao file
Tinh định thức của ma trận vuông bằng cách dùng công thức hoán vị,từ đó tìm hạng của ma trận và ghi vào file
Hiển thi ra màn hình các kết quả khi có yêu cầu
Với các yêu cầu như trên thì chương trình sẽ bao gồm 7 phần tương ứng với 8 mục đầu trong menu chính của chương trình :
Trong đó các hàm được xây dựng theo cấu trúc sau :
Chương trình chính sẽ gọi là main ( )
Trang 4Từ hàm main se gọi đến 1 trong 7 hàm : nhapmatran ,
matranngaunhien , tongmatran , hieumatran , tichmatran ,
dinhthucvahangmatran , hienthifile
1 Nhapmatran :
Hàm này làm việc theo một trong hai cách :
+ Nhập ma trận từ file : Gọi hàm tạo file mình đã tạo sẵn:
Hàm Matrannhaptufile ( ); sẽ lấy file có sẵn ở hàm tạo file có trước
“Input.txt” để tạo dữ liệu đầu vào một cách ngẫu nhiên cho chương trình tùy
theo sụ lựa chọn
Hàm Nhapmatran ( ); sẽ tạo file với dữ liệu nhập từ bàn phím
Trong hàm nhapmatran ( );ta xây dựng 3 ma trận sử dụng cho toàn bộ chương trình :ma trận A ,B và ma trận vuông C với dữ liệu lấy một cách
ngẫu nhiên từ bàn phím và lưu chúng vào file
Trong hàm Matrannhaptufile ( ); ta cũng xây dựng tương tự 3 ma trận
A,B,C với dữ liệu lấy từ file
2 Matranngaunhien :
Hàm này tạo ma trận A,B và ma trận vuông C một cách ngẫu nhiên ,lưu
chúng vào file và sử dụng cho toàn bộ chương trình
Để tạo được như vậy ta sử dụng hàm rand ( );
6 Dinhthucvahangmatran :
Hàm dinhthucvahangmatran ( ); sẽ đưa ra định thức và hạng của ma trận vuông C Trong hàm này thì nó gọi hàm dinhthuc ( ); và hàm hang ( ); Hàm dinhthuc ( ); sẽ đưa ra thủ tục để tính định thức và hàm hang ( ); sẽ
đưa ra thủ tục để tính hạng nhưng sau khi đã xây dựng được hàm
dinhthuc(); của ma trận vuông C.
7 Hienthifile :
Hàm hienthifile ( ); dùng để hiện thị tất cả các file đã tạo và sử dụng
trong suốt quá trình làm việc :
Trang 5+ Hiển thị file chứa toàn bộ các ma trận đã được nhập vào (đó là
ma trận A,B,C)
+Hiển thị file chứa toàn bộ quá trình thiết lập để tính và hiện thị ra
được kết quả của tích ma trận (ma trận D), tổng ma trận(ma trận E), hiệu ma trận(ma trận F), định thức ma trận và hạng của ma trận
*******************************************************
B SƠ ĐỒ THUẬT TOÁN
Trong đề tài này để xây dựng và hoàn thiện chương trình thì ta phải xâydựng sơ đồ thuật toán với mục đích :
Tránh những lỗi logic khi thực hiện chương trình
Giúp cho người đọc dễ dàng hiểu được code của chươngtrình
Để giải quyết được các yêu cầu trong đề tài này thì ta cần làm :
1 Tạo dữ liệu để sử dụng trong suốt chương trình (nhapmatran)
Dữ liệu đầu vào chính là xây dựng hai ma trận bất kỳ A[m][n], B[p][q] và
ma trận vuông C[n1][n1] Việc xây dựng 3 ma trận này tương tự như nhau làđều sử dụng hai vòng lặp for.Tuy nhiên có hai cách để xây dựng chúng :Thiếtlập ma trận với số liệu lấy nhập bàn phím và thiết lập ma trận một cách ngẫunhiên :
Sau khi tạo được bằng một trong hai cách ta phải in được các ma trận đó
ra màn hinh : Ta cũng sử dụng hai vòng lặp for :
Trang 61.3 Ma trận đọc từ file
Đầu tiên ta phải tạo được dữ liệu đầu vào tức là ta xây dựng file
“Input.txt”, khai báo sâu kiểu chr msg [25]
Ta sử dụng hàm fgets để đọc dữ liệu và sử dụng hàm atoi ( hàm chuyển ký
tự thành số ) ví dụ như m = atoi(msg) Sau đó ta hiển thị ra bằng cách sử dụng hai vòng lặp for :
+ Nếu điều kiện này được thỏa mãn thì ta tiến hành tính tổng của hai
ma trận này ( giả sử ma trận tổng là E[m][n] )
Ta dùng hai biến chạy i (1<=i<=m )và j (1<=j<=n ) , ma trận tổng E[ i ][ j ] = A[ i ][ j ] + B[ i ][ j ]
Ta minh họa bằng thuật toán:
for ( i=1 ; i<=m ; i++)
for ( j=1 ; f<=n ; j++ )
{
E[ i ][ j ] = A[ i ][ j ] + B[ i ][ j ]
}
Sau đó ta hiển thị ma trận lên màn hình
for ( i=1 ; i<=m ; i++)
{
for ( j=1 ; f<=n ; j++ )
printf ( “%10.2f “ , E[ i ][ j ] ) ;
}
+ Nếu điều kiện này không thỏa mãn thì không tồn tại tổng
Ta minh họa thuật toán tính tổng bằng sơ đồ giải thuật :
Trang 7+ Nếu điều kiện này được thỏa mãn thì ta tiến hành tính hiệu của hai
ma trận này ( giả sử ma trận hiệu là F[m][n] )
Ta dùng hai biến chạy i (1<=i<=m )và j (1<=j<=n ) , ma trận hiệu F[ i ][ j ] = A[ i ][ j ] - B[ i ][ j ]
Ta minh họa bằng thuật toán:
for ( i=1 ; i<=m ; i++)
for ( j=1 ; f<=n ; j++ )
{
F[ i ][ j ] = A[ i ][ j ] - B[ i ][ j ]
}
Sau đó ta hiển thị ma trận hiệu lên màn hình
for ( i=1 ; i<=m ; i++)
{
for ( j=1 ; f<=n ; j++ )
printf ( “%10.2f “ , F[ i ][ j ] ) ;
}
+ Nếu điều kiện này không thỏa mãn thì không tồn tại hiệu
Ta minh họa thuật toán tính hiệu bằng sơ đồ giải thuật :
BEGIN
NHẬP MA TRẬN
TỔNG MA TRẬN
ENDm=p&n=
q
Trang 8Tức là : ( n==p )
+ Nếu điều kiện này được thỏa mãn thì ta tiến hành tính tích của hai
ma trận này ( giả sử ma trận tích là D[ m ][ q ] )
Ta dùng hai biến chạy i (1<=i<=m )và j (1<=j<=q ) ,
Sau đó ta gán D[ i ][ j ] =0 và lấy hàng i của ma trận A nhân với cột j của ma trận B Để làm được điều này ta dùng biến trung gian k ( 1<=k<=n )
ma trận tích là :
D[ i ][ j ] = A[ i ][ k ] * B[ k ][ j ]
Ta minh họa thuật toán như sau :
for ( i=1 ; i<=m ; i++)
Sau đó ta hiển thị ma trận tích lên màn hình
for ( i=1 ; i<=m ; i++)
BEGIN
NHẬP MA TRẬN
HIỆU MA TRẬN
ENDm=p&n=
q
Trang 9{
for ( j=1 ; f<=q ; j++ )
printf ( “%10.2f “ , D[ i ][ j ] ) ;
}
+ Nếu điều kiện này không thỏa mãn thì không tồn tại tích
Ta minh họa thuật toán tính tích bằng sơ đồ giải thuật :
2.4 Hạng và định thức của ma trận vuông ( dinhthucvahangmatran )
Theo yêu cầu của đề tài thì ta phải tìm được định thức của ma trận vuông C[n1][n1] trước sau đó mới suy ra hạng
Trước hết ta tìm định thức của ma trận :
Ta dùng kiểu boolean : đặt done=0 ( FALSE )
Nếu như đúng while ( ! done ) thì thuật toán sẽ như sau:
+ Nếu có phần tử trên đường chéo chính bằng không ( C[ i][j ]==0 )
ta đặt giá trị đó là max=0 và m1=i ( gán hàng i là hàng m1)
Dùng một biền phụ k cho biến này chạy (k=i+1 ; k<n1 ; k++ )
Nếu max < trị tuyệt đối của phần tử C[ k ][ i ] thì hàng m1 trở thành hàng k và max = fabs ( C[ k ][ i ] )
Nếu ( m1! = i ) thì ta hoán đổi hàng i và hàng m1và giá trị của định thức d=-d
Nếu ( m1 == i ) thì ma trận lúc này suy biến done lúc này=1 và d=0
Ta minh họa bằng thuật toán như sau
Trang 10c = C[ i ][ j ];
C[ i ][ j ] = C[m1][ j ];
C[m1][ j ] = c; /* doi hang i va hang m1 */
} }
+2 Tiến hành khử hàng :Ta dùng biến trung gian k ( k chạy từ i+1 tới n1 ) sau đó tiến hành khử hàng thứ k theo quy tắc hình chữ nhật
for ( j = i+1 ; j<n1 ; j++ ) C[ k ][ j ] = C[ k ][ j ] - C[ i ][ j ] * C[ k ][ i ];
C[ k ][ i ] = 0;
} Sau đó cho i tăng :Nếu ( i>=n1 ) thì cho i chạy từ 0 tới n1 và định thức lúc này chính là tích của các phần tử trên đường chéo chính tức là :
d = d * C[ i ][ i ]
Trang 11Ta minh họa như sau
enum BOOLEAN {false=0,true} t1;
Như ta đã biết hạng của ma trận dạng bậc thang bằng số hàng khác không của nó và theo cách tính định thức trên thì ta đã biến đổi ma trận C[n1][n1] thành dạng bậc thang nên ta sẽ tim hạng thông qua số hàng khác không của
ma trận hình thang này :
Đặt t1 lúc đầu là true tức là các phần tử hàng khác không và gán i = n1-1Trong khi xảy ra ( t1 ) thì sau đó ta làm như sau : Cho j chạy từ i đến n1 Để cho tiện ta đặt một biến trung gian tg = C[ i ][ j ]
Nếu t1 = false ( các phần tử trên hàng i bằng không ) thi ta tiến hành giảm i xuống và cứ như thế kiểm tra đến khi nào t1=true.và hạng ma trận là : i+2 ( do ban đầu ta gán i = n1-1 va sau đó lại giảm i nên hạng ma trận là i+2 )
Ta minh họa như sau :
Trang 12CHƯƠNG III : MÃ NGUỒN
printf("\n vao so hang m, so cot n cua ma tran A\n");
fprintf(stream,"\n vao so hang m, so cot n cua ma tran A\n");
Trang 13printf("\n vao so hang p, so cot q cua ma tran B\n");
fprintf(stream,"\n vao so hang p, so cot q cua ma tran B\n");
printf("\n vao cap cua ma tran vuong C\n");
fprintf(stream,"\n vao cap cua ma tran vuong C\n");
printf("Ma tran A\n");
fprintf(stream,"\n Ma tran A\n");
printf(" %d %d",m,n);
fprintf(stream," %d %d",m,n);
for(i=1;i<=m;i++)
Trang 15fprintf(stream,"\n vao so hang m, so cot n cua ma tran A\n");
printf("\n vao so hang p, so cot q cua ma tran B\n");
fprintf(stream,"\n vao so hang p, so cot q cua ma tran B\n");
printf("\n Vao cap cua ma tran C\n");
fprintf(stream,"\n Vao cap cua ma tran C\n");
printf("\n Ma tran A\n");
fprintf(stream,"\n Ma tran A\n");
Trang 18printf("\n tong hai ma tran\n");
fprintf(stream,"\n tong hai ma tran\n");
printf("%10.4f",E[i][j]);
fprintf(stream,"%10.4f",E[i][j]);
} printf("\n");
printf("\n hieu hai ma tran\n");
fprintf(stream,"\n hieu hai ma tran\n");
fprintf(stream,"%12.4f",F[i][j]);
Trang 19} printf("\n");
printf("\n tich hai ma tran\n");
fprintf(stream,"\n tich hai ma tran\n");
fprintf(stream,"%15.3f",D[i][j]);
} printf("\n");
printf("\n tinh dinh thuc ma tran\n");
fprintf(stream,"\n tinh dinh thuc ma tran\n");
Trang 20c=C[i][j];
C[i][j]=C[m1][j];
C[m1][j]=c; /* doi hang i va hang m1 */
} }
if(m1==i)
{
done=1;
printf("\n Ma tran la suy bien!\n");
fprintf(stream,"\n Ma tran la suy bien!\n");
for(j=i+1;j<n1;j++) C[k][j]=C[k][j]-C[i][j]*C[k][i];
C[k][i]=0;
} }
printf("\n lan khu hang %d",i);
fprintf(stream,"\n lan khu hang %d",i);
Trang 21{
for(i=0;i<n1;i++)
d=d*C[i][i];
printf("\n Dinh thuc cua ma tran=%-10.4f\n",d);
fprintf(stream,"\n Dinh thuc cua ma tran=%-10.4f\n",d);
printf("\n Hang ma tran=%d",i+2);
fprintf(stream,"\n Hang ma tran=%d",i+2);
printf("\n BAM PHIM BAT KY DE TRO RA ! PRESS ");
fprintf(stream,"\n BAM PHIM BAT KY DE TRO RA ! PRESS ");
printf("\n\n\n khong ton tai tong !");
fprintf(stream,"\n\n\n khong ton tai tong !");
printf("\n BAM PHIM BAT KY DE TRO RA ! PRESS ");
}
getch();
fclose(stream);
Trang 22printf("\n\n\n khong ton tai hieu !");
fprintf(stream,"\n\n\n khong ton tai hieu !");
printf("\n BAM PHIM BAT KY DE TRO RA ! PRESS ");
printf("\n\n\n khong ton tai tich !");
fprintf(stream,"\n\n\n khong ton tai tich !");
printf("\n BAM PHIM BAT KY DE TRO RA ! PRESS ");
Trang 27case DOWN:
j++;
if(j==9)
{ j=0 ; } break;
Trang 28CHƯƠNG IV : ĐÁNH GIÁ THUẬT TOÁN VÀ CHƯƠNG TRÌNH
I ĐÁNH GIÁ THUẬT TOÁN
Trong chương trinh ta có sử dụng thuật toán là : duyệt tuần tự các phần
tử trên đường chéo chính của ma trận C và khi tính hạng ta cũng sử dụng phương pháp duyệt để tìm các hàng khác không Ta đánh giá độ phức tạp tính toán như sau :
1.1 Duyệt các phần tử trên đường chéo chính
Đối với giải thuật này chính là phép di chuyển con trỏ dùng để duyệt và
so sánh với 0 Nếu tìm được phần tử bằng không thì thuật toán dừng và kết luận Do duyệt tuần tự nên số phép dịch chuyển bằng số phép so sánh Giả sử ma trận là cấp n thì sẽ có n lần duyệt danh sách :
+ Trong trường hợp tốt nhất :( phần tử đầu tiên C[ 1 ][ 1 ] = 0 )
Tại bất cứ lần duyệt nào cũng chỉ làm một phép so sánh
Độ phức tạp tính toán trong trường hợp này là : T(n) = O(1)
+ Trong trường hợp xấu nhất :(duyệt đến tận phần tử cuối C[ n ]
[ n ]=0)
Tổng số phép so sánh :n
Độ phức tạp tính toán : T(n) = O(n)
+ Trong trường hợp trung bình : ( Coi các phần tử có xác suất xuất hiện
là số không tại các vị trí là như nhau )
Ta chỉ cần làm một phép so sánh
Độ phức tạp tính toán trong trường hợp này là : T(n) = O(1)
+ Trong trường hợp xấu nhất : (ta phải duyệt đến hàng đầu tiên của ma trận )
Tại lần duyệt thứ i cần làm i phép so sánh
Tổng số lượng phép so sánh :
n i
1
=
2
)1(
22/ =
Trang 29Sau khi cho chạy thử với bộ dữ liệu đầu vào khác nhau thì thu được một
số đánh giá sau :
Tốc độ :
Ma trận nhập vào với kích thước lớn ( <=.15 ) thì việc tính toán
cộng , trừ nhân hai ma trận là không lâu lắm Tốc độ tính toán trong giải thuật tính định thức và tìm hạng của ma trận với kích thước nhỏ là không lâu
lắm.Tuy nhiên việc hiển thị ra file trên fỏm của C thì phải tiến hành cắt các trường thông tin nên hiển thị file chậm hơn so với Pascal Điều này không phải do giải thuật mà do việc xử lý trên file text
Độ tin cậy :
Chương trình cho kết quả đúng với nhiều dữ liệu đầu vào khác nhau nhưng chỉ với các ma trận có kích thước (<=15).Tuy nhiên với ma trận có kích thước lớn thì em chưa xử lý được Trong quá trình tính định thức của matrận vuông thì việc tính toán cũng chỉ áp dụng được với các ma trận có kích thước nhỏ(<=7),nếu ma trận có kích thước lớn thì tính toán sẽ gặp sai số và ảnh hưởng đến kết quả cũng như hạng của ma trận
Lời tựa :
Trong quá trình làm đề tài này dù em đã cố gắng rất nhiều nhưng cũng khôngthể tránh khỏi những thiếu xót và một số vấn đề chưa giải quyết được Em rấtmong sự giúp đỡ của cô giáo để hoàn thiện chương trình này hơn