CÁC CHỦ ĐỀ CHÍNH 1. GIỚI THIỆU FORTRAN ● Lịch sử và mục đích của Fortran ● Các thành phần trong FORTRAN ◆ ◆ ◆ ◆ ◆
Cấu trúc của chương trình Fortran Kiểu dữ liệu và các khai báo đặc biệt khác Các tính chất của các chương trình điều khiển Nhập xuất (Input/Output – I/O) trong Fortran subfunctions and subroutines
2. Cách sử dụng Fortran 90 trong MS Fortran Power Station 4.0 3. Sử dụng các phần mềm hỗ trợ vẽ đồ thị minh họa dữ liệu: - MS Excel - Grapher (Golden Software)
LỊCH SỬ FORTRAN ● ●
Tên viết tắt của FORmular TRANslator Một trong những ngôn ngữ lập trình cũ nhất ◆ ◆
●
Các phiên bản của Fortran ◆ ◆ ◆ ◆ ◆ ◆ ◆
● ●
John Backus đã tạo ra và phát hành vào năm 1957 Được thiết kế cho các tính toán trong khoa học kỹ thuật FORTRAN 1957 FORTRAN II FORTRAN IV FORTRAN 66 (được phát hành theo tiêu chuẩn ANSI 1966) FORTRAN 77 (chuẩn ANSI 1977) FORTRAN 90 (Chuẩn ANSI 1990) FORTRAN 95 (Chuẩn ANSI mới nhất)
Có nhiều phiên bản ‘bản địa hóa’ khác nhau Có nhiều chương trình tính toán trong khoa học kỹ thuật được viết sẵn dưới dạng các SubFunction hoặc SubRoutine
TẠI SAO PHẢI CHỌN FORTRAN ●
● ● ● ● ● ●
FORTRAN được tạo ra để viết các chương trình giải các bài toán khoa học kỹ thuật Đưa vào kiểu biến nguyên và dấu chấm động (floating point) Đưa vào kiểu dữ liệu mảng cho các tính toán toán học Đưa vào các subroutines và subfunctions Trình biên dịch có thể tạo ra mã tối ưu cao (chạy nhanh) Có sẵn rất nhiều thư viện số toán (numerical-math) Các khó khăn và nhược điểm của Fortran: ◆ ◆ ◆ ◆
Cho phép sử dụng lệnh GO TO rất tự do ⇒ Khó để đọc hiểu các đoạn mã lệnh và làm rối chương trình Khó kiểm soát các dữ liệu dạng phi số (nonnumerical) Không có khả năng lập trình đệ qui
Xây dựng chương trình FORTRAN
Trình biên dịch (Compiler) FORTRAN
Chương trình FORTRAN
Liên kết với các thư viện
File thực thi
Source Code
Object Code
Libraries
Executable Code
Mã nguồn
Mã đối tượng
Thư viện
Mã thực thi
Sửa đổi lại chương trình (nếu có)
Kiểm tra và phát hiện lỗi chương trình
Thực thi chương trình
Định dạng của chương trình FORTRAN FORTRAN 77 cần những định dạng cố định (*.for) Phần chương trình được bắt đầu từ cột số 7 Phần chú thích bắt đầu từ chữ ‘c’ đặt tại cột số 1 Dấu ‘*’ được đặt tại cột số 6 để nối dòng trên với dòng dưới
-
PROGRAM MAIN C COMMENTS ARE ALLOWED IF A “C” IS PLACED IN COLUMN #1 DIMENSION X(10) READ(5,*) (X(I),I=1,10) WRITE(6,1000) X 1000 FORMAT(1X,’THIS IS A VERY LONG LINE OF TEXT TO SHOW HOW TO CONTINUE ’ *
‘THE STATEMENT TO A SECOND LINE’,/,10F12.4) End
1-5 6 dành cho nhãnl
7-72 dành cho các câu lệnh của chương trình Thường dành cho lệnh xuống dòng (dùng dấu * đặt tại cột số 6)
73-80
Định dạng của chương trình FORTRAN FORTRAN 90/95 ◆ ◆ ◆
Cho phép viết chương trình ở dạng tự do Những ghi chú được đặt ngay sau dấu (!) Hỗ trợ đặt tên biến dài (tối đa 31 ký tự)
PROGRAM MAIN ! Phần sau dấu ‘!’ là phần chú thích DIMENSION X(10) READ(5,*) (X(I),I=1,10) WRITE(6,1000) X 1000 FORMAT(1X,’THIS IS A VERY LONG LINE OF TEXT TO SHOW HOW TO CONTINUE ’& ‘THE STATEMENT TO A SECOND LINE’,10F12.4) ! Để xuống dòng quá dài, sử dụng dấu ‘&’ đặt ở sau vị trí cuối của dòng bên trên End
1
80
Cấu trúc chương trình FORTRAN ●
●
Hầu hết các chương trình FORTRAN gồm có 1 chương trình chính và một hoặc nhiều chương trình con (Function hay Subroutine) Cấu trúc của chương trình FORTRAN: Program XXXX Các khai báo (Declarations): biến, hằng,… Các biến ban đầu (Variable initializations) Phần thân chương trình Các định dạng xuất nhập (nếu có) END Các chương trình Con functions & subroutines)
Các khai báo kiểu dữ liệu (Data Type Declarations) ●
Các kiểu dữ liệu cơ bản ◆ ◆ ◆ ◆ ◆ ◆
●
Kiểu biến nguyên và biến thực có thể được qui định số byte dành cho biến đó: ◆ ◆
●
Theo ngầm định là 4 bytes (ví dụ ta khai báo biến: INTEGER*4 hoặc REAL*4 tương đương với REAL hoặc INTEGER DOUBLE PRECISION tương đương với REAL*8
Các mãng (array) được khai báo: ◆ ◆
●
INTEGER – kiểu số nguyên (+/-) REAL – kiểu số thực DOUBLE PRECISION – mở rộng độ chính xác CHARACTER*n – kiểu chuỗi ký tự (n là số ký tự) LOGICAL – kiểu luận lý ( trả về giá trị .TRUE. hoặc .FALSE.) COMPLEX – kiểu số phước
DIMENSION A(3,5) hoặc REAL A(3,5): Mãng 2 chiều kích thước 3x5 CHARACTER*30 NAME(50) – Cách khai báo trực tiếp một mãng ký tự có 50 phần tử, mỗi phần tử có thể chứa tối đa 30 ký tự
FORTRAN 90/95 còn cho phép lập trình viên tự định nghĩa kiểu dữ liệu
Các khai báo ẩn và hiện Implicit vs Explicit Declarations ●
Theo ngầm định, dạng biến ẩn được qui định như sau ◆ ◆
●
Chúng ta cũng có thể khai báo IMPLICIT: ◆ ◆ ◆
●
Các biến bắt đầu từ ký tự: A-H, O-Z dành cho biến thực (REAL) bytes) Các biến bắt đầu từ các ký tự: I-N dành cho biến (INTEGER) IMPLICIT REAL (A-Z): Khai báo tất cả các biến là biến thực REAL nếu nó không được khai báo IMPLICIT CHARACTER*2 (W): Khai báo những biến bắt đầu từ ký tự ’W’ có kiểu dữ liệu là ký tự kích thước 2 ký tự IMPLICIT DOUBLE PRECISION (D) Khai báo cho những biến bắt đầu từ ký tự ’D’có kiểu dữ liệu là ‘độ chính xác kép’ (kích thước biến là 8 bytes)
Nên: Khai báo tất cả các biến ở dạng hiện explicit ◆
IMPLICIT NONE v(nếu dùng lệnh này thì tất cả các biến phải được khai báo
Các khai báo khác ●
Định nghĩa các hằng số (các tham số) ◆ ◆ ◆ ◆
●
PARAMETER (PI=3.1415927, NAME=‘FORTRAN’) PARAMETER (PIO2=PI/2, FLAG=.TRUE.) Các tham số trên sẽ không thay đổi trong toàn bộ chương trình Cũng có thể sử dụng những tham số này để định nghĩa tham số khác
Các biến ban đầu ◆ ◆ ◆
◆
◆
◆
DATA Dùng để khởi tạo các giá trị ban đầu của biến DIMENSION A(10,10)! Mãng số thực A kích thước 10x10 DATA A/100*1.0/! Tất cả các biến trong mãng A ban đầu có giá trị là 1.0 DATA A(1,1),A(10,1),A(5,5) /2*4.0,-3.0/ - Gán giá trị ban đầu: A(1,1)= A(10,1)=4.0 và A(5,5)=-3 DATA ((A(I,J),I=1,5,2),J=1,5) /15*2.0/ - initialize with implied-do list …
Các phép toán số học ●
Độ ưu tiên tăng dần từ trên xuống Toán tử ** * / + -
●
hàm lũy thừa nhân chia cộng trừ
Những biểu thức nằm trong dấu () có độ ưu tiên lớn nhất
Các biểu thức so sánh Toán tử .LT. hoặc < .LE. hoặc <= .EQ. hoặc == .NE. hoặc /= .GT. hoặc > .GE. hoặc >=
Quan hệ nhỏ hơn nhỏ hơn hoặc bằng Bằng khác (không bằng) lớn hơn lớn hơn hoặc bằng
Các biểu thức luận lý (logic) ●
●
●
Gồm một hoặc nhiều biểu thức logic chỉ nhận một trong hai giá trị: .TRUE. hoặc .FALSE. Các toán tử: Toán tử
Ví dụ
Ý nghĩa
.AND. .OR. .NEQV. .XOR. .EQV. .NOT.
A .AND. B A .OR. B A .NEQV. B A .XOR. B A .EQV. B .NOT. A
Toán tử logic AND Toán tử logic OR Toán tử logic không bằng Toán tử logic XOR (giống như .NEQV.) Toán tử logic bằng Toán tử logic NOT (phủ định)
Cần phải xét đến độ ưu tiên của các toán tử trên toàn bộ biểu thức
Độ ưu tiên của các toán tử ●
●
Gồm một hoặc nhiều biểu thức logic chỉ nhận một trong hai giá trị: .TRUE. hoặc .FALSE. Các toán tử: Loại (Category)
Toán tử (Operator)
Độ ưu tiên (Precedence)
Số (numeric)
**
Cao nhất
Số
* or /
Số
unary + or -
Số
binary + or -
Ký tự (character)
//
Quan hệ (ralational)
.EQ. .NE. .LT. .LE. .GT. .GE.
Luận lý (logical)
.NOT.
Luận lý
.AND.
Luận lý
.OR.
Luận lý
.XOR. .EQV. .NEQV.
Thấp nhất
Mảng (Array) trong Fortran ● ●
Mảng trong Fortran là mảng 1 hoặc nhiều chiều (tối đa 7 chiều). Khai báo mảng bằng cách sử dụng dấu ‘()’ ◆ ◆
● ●
TEST(3) FORCE(4,2)
! Mảng 1 chiều, kích thước 3 ! Mảng 2 chiều, kích thước 4x2
Kích thước mảng được qui định là số nguyên từ 1…N Có thể khai báo mảng dưới nhiều dạng khác nhau REAL*4 L(2,5) !L là mảng số thực 4 bytes, kích thước 2x5 ◆ INTEGER*4 K(1:12) hoặc K(12) ◆ !K là mảng số nguyên 4 bytes, kích thước 12 (gồm 12 phần tử) chỉ số từ 1-12 - Parmeter (n=10, m=20) Mảng K kích thước 20 (phần tử), mảng I kích thước 10x20 - Dimension K(n), I(n,m) ◆
●
Mảng được lưu trữ dưới theo cột trước, hàng sau
Câu lệnh rẻ nhánh: IF ELSE IF ●
Cấu trúc cơ bản: ◆
◆
Cú pháp: IF (biểu thức logic_1) THEN các câu lệnh thực thi (1) ELSE IF (biểu thức logic_2) THEN các câu lệnh thực thi (2) ELSE các câu lệnh thực thi (3) ENDIF VD: IF (KEY.EQ.1) THEN CLASS=‘FRESHMAN’ ELSE IF (KSTAT.EQ.2) THEN CLASS=‘SOPHOMORE’ ELSE IF (KEY.EQ.3) THEN CLASS=‘JUNIOR’ ELSE IF (KEY.EQ.4) THEN CLASS=‘SENIOR’ ELSE CLASS=‘UNKNOWN’ ENDIF
IF THEN ELSE ●
Cấu trúc cơ bản: ◆
◆
◆
Cú pháp: IF (biểu thức logic) THEN các câu lệnh thực thi (1) ELSE Các câu lệnh thực thi (2) ENDIF Nếu biểu thức logic là đúng thì chương trình sẽ thực thi các câu lệnh (1), ngược lại, biểu thức logic sai, các câu lệnh (2) sẽ được thực thi VD: IF (KEY.EQ.0) THEN X=X+1 đúng KEY= 0? X=X+1 ELSE sai X=X+2 X=X+2 ENDIF
Vòng lặp Cú pháp: DO nhãn , điều khiển vòng lặp các câu lện thực thi Nhãn Continue ◆ VD: DO 100 K=1,10
Hoặc
DO điều khiển vòng lặp các câu lện thực thi ENDDO
DO K=1,10
PRINT*,A(K)
PRINT*,A(K)
100 CONTINUE
ENDDO
DO K=1,10,2 PRINT*,A(K) ENDDO
Các lệnh điều khiển trong FORTRAN ● ● ● ● ● ●
● ●
● ●
GO TO : Nhảy chương trình đến 1 vị trí nào đó Lện điều kiện IF (IF, hoặc IF-ELSE,… ) CASE (gần giống IF) Vòng lặp (DO, DO WHILE) CONTINUE! Đánh dấu tiếp tục dòng kế tiếp PAUSE! Tạm dừng chương trình chờ nhấn 1 phím bất kỳ để tiếp tục STOP! Ngừng hẳn chương trình CALL! Gọi chương trình con hoặc các thư viện viết sẵn RETURN! Trả về lại vị trí của lệnh CALL END! Kết thúc chương trình chính
Các thủ tục nhập/xuất (I/O) ●
Các lệnh cơ bản ◆
◆
◆
READ – nhận (đọc) dữ liệu đầu vào từ thiết các thiết bị nhập hoặc từ file WRITE – ghi (xuất) dữ liệu ra các thiết bị xuất như màn hình, máy in, file,… FORMAT – định dạng cho nhập xuất dữ liệu
Lệnh Read ●
Dùng lệnh READ có điều khiển bằng định dạng Cú pháp: READ(dev_no, format_label) variable_list ! dev_no: mã số thiết bị ngoại vi – format_label: nhãn định dạng) ! Đọc biến từ thiết bị ngoại vi nào đó theo định dạng ◆ VD: READ(5,1000) A,B,C 1000 FORMAT(3F12.4) Đọc biến A, B, C từ thiết bị ngoại vi ‘5’ theo định dạng là số thực, gồm 12 chữ số với 4 chữ số thập phân READ(*,*) A,B,C Đọc biến A, B, C từ màn hình (nhập bằng bàn phím) với định dạng tùy ý ◆ Dùng READ với vòng lặp ◆ VD: READ(5,1000)(A(I),I=1,10) 1000 FORMAT(10F12.4) ◆
Lệnh Write ●
Dùng lệnh WRITE có điều khiển bằng định dạng Cú pháp: WRITE(dev_no, format_label) variable_list ! Ghi biến trong variable_list đến thiết bị ngõ xuất dev_no, theo định dạng đã được qui định tại format_label ◆ VD: WRITE(6,1000) A,B,KEY 1000 FORMAT(F12.4,E14.5,I6) ! Ghi vào thiết bị ‘6’ biến A, B, KEY theo định dạng 1000 WRITE(*,*) A,B,KEY ! Ghi các biến A, B, KEY ra màn hình theo định dạng bất kỳ ◆ Có thể ghi các biến bằng vòng lặp WRITE(6,2000)(A(I),I=1,10) ◆
Lệnh Format ●
Cấu trúc chung ◆ ◆
4
Cú pháp: label_no FORMAT(format-specifiers) VD: WRITE(6,1000) A,B,KEY FORMAT(F12.4,E14.5,I6)
chỉ số nhãn label_no
Định dạng format-specifiers - Biến A là số thực gồm 12 chữ số, trong đó có 4 chữ số thập phân - Biến B là số thực được viết dưới dạng hàm mủ VD: A=9.12345 = 912345E-5 - Biến KEY là biến nguyên có 6 chữ số
Các đặc tả bên trong lệnh Format ● ● ● ● ● ● ● ● ● ● ● ●
Iw[.m] Bw[.m] Ow[.m] Zw[.m] Fw.d Ew.d[Ee] ENw.d[Ee] ESw.d[Ee] Gw.d[Ee] Dw.d Lw A[w]
Kiểu số nguyên Kiểu số nhị phân Kiểu số bát phân Kiểu số thập lục phân Kiểu số thực Kiểu số thực dưới dạng hàm mủ Kiểu số thực dưới dạng ký hiệu dùng trong kỹ thuật Kiểu số thực dưới dạng ký hiệu dùng trong khoa học Kiểu số thực với dải mở rộng Kiểu số thực với độ chính xác kép Kiểu số luận lý (logical) Kiểu số ký tự
Các đặc tả bên trong lệnh Format ●
Mã định dạng: X ◆ ◆ ◆
●
Mã định dạng: I ◆ ◆
●
Cú pháp: Iw Định dạng cho số nguyên có độ rộng (số chữ số, kể cả dấu) w. Nếu số nguyên này có số chữ số lớn hơn w thì nó được hiển thị thành w dấu *
Mã định dạng: F ◆ ◆
●
Cú pháp: nX Qui định n khoảng trắng ngay tại vị trí đó VD: 100 Format(2x,F5.2,x,F5.2)
Cú pháp: Fw.d Định dạng số thực có độ rộng (số chữ số, kể cả dấu và dấu chấm thập phân) w và d số chữ số thập phân
Mã định dạng: A ◆ Cú pháp: A hoặc Aw ◆
Định dạng cho kiểu ký tự có độ rộng là A ký tự, hoặc nếu sử dụng dạng Aw thì các khoảng trắng sẽ được thêm vào bên phải của biến nếu như các ký tự sử dụng ít hơn w
Lệnh OPEN ●
OPEN thường được sử dụng kèm với READ & WRITE ◆
◆
Cú pháp thường dùng: OPEN ([UNIT=]io_unit [,FILE=name] [,status=]slist) VD: OPEN (UNIT=1,FILE=‘D:\test\test1.dat’,STATUS=‘OLD’) !Mở file test1.dat trong thư mục D:\test. Thường dùng để mở 1 file có sẵn để đọc. OPEN (2,FILE=‘D:\test\test2.dat’,STATUS=‘new’) !Luôn luôn tạo 1 file có tên test2.dat trong thư mục D:\test. Thường dùng để tạo 1 file mới để ghi kết quả tính toán vào đó. OPEN (3,FILE=‘D:\test\test3.dat’,STATUS=‘unknown’) ! Kiểm tra trong thư mục D:\test, nếu đã có file test3.dat thì mở file đó, nếu chưa có thì tạo ra 1 file mới có tên test3.dat. Cú pháp này thường dùng để tạo ra 1 file dữ liệu trong chương trình tính, khi tính toán lại nó sẽ ghi đè lên file cũ.
Cách truy xuất file Thông thường chúng ta truy xuất file để đọc và ghi số liệu vào đó VD1: Muốn đọc File dữ liệu ‘Test.dat’ vào mãng A(n) ●
… Open (Unit=1, File=‘test.dat’, status=‘old’) …
1.0 4.0 2.0 4.0 3.0 4.0
Enddo …
Read(1,*)(A(i), i=1,3)
A(1)=1 A(2)=2 A(3)=3
Chú Ý: Các dữ liệu nhập vào được phân biệt nhau bằng các ký tự: - Một hoặc nhiều khoảng trắng - Dấu ‘,’ - Ký tự xuống dòng
Open (Unit=1, File=‘test.dat’, status=‘old’) …
Do i=1,3 Read(1,*)A(i)
…
…
A(1)=1 A(2)=4 A(3)=2
Lệnh OPEN + CLOSE ● ●
OPEN thường được sử dụng kèm với READ & WRITE Thường ở cuối chương trình thường đi kèm với lệnh CLOSE VD: OPEN (UNIT=1,FILE=‘D:\test\test1.dat’,STATUS=‘OLD’) OPEN(UNIT=2,FILE=‘result.dat’,STATUS=‘unknown’) !Mở file result.dat READ (1,*)(A(i),i=1,n) !Đọc file test.dat vào mảng A(n) (n phần tử) Do i=1,n B(i)=A(i)+i Write (2,*)B(i) Enddo ! Ghi vào file result.dat giá trị của mãng B … CLOSE (1) CLOSE (2) … END
◆
Intrinsic Functions: các nội hàm trong Fortran ●
● -
Fortran có sẵn hầu hết các hàm cơ bản: - Hàm lượng giác: SIN, COS, TAN, SINH,… - Hàm Lũy Thừa - Hàm Logarith - Mod, … Các thư viện sẵn có: Giải các hệ phương trình tuyến tính Các chương trình tính Max, Min, Average,… …
Chương trình con: Function và Subroutine Giống như Procedure của các ngôn ngữ lập trình khác - Function: Trả về 1 giá trị thông qua tên hàm - Subroutine: trả về 1 biến thông qua đối số của biến ● Cấu trúc của các chương trình con giống như chương trình chính ● Được đặt ở cuối chương trình chính VD: ●
Program Test … END Subroutine Test 1 … Return END Subroutine Integer Function (num) … Return END Function
Chương trình con: Subroutine ●
Lưu Ý Cách viết giống như viết chương trình chính Tầm vực (scope) của biến
◆ ◆
–
–
Biến toàn cục: những biến được khai báo trong chương trình chính Biến cục bộ: những biến được khai báo trong chương trình con
Cách gọi chương trình con subrountine
◆
Program Test
Program Test
…
…
Call Test1(X,Y)
Call Test1(X,Y)
END
END
Subroutine Test 1(A,B)
Subroutine Trung binh(A, Tbinh)
…
…
Return
Return
END Subroutine
END Subroutine
Bài tập BT 1: Giải phương trình bậc hai bằng các hệ số được yêu cầu nhập từ bàn phím. (chỉ tính cho trường hợp nghiệm thực) BT 2: Viết chương trình nhập vào một ma trận hệ số của 1 hệ phương trình tuyến tính n ẩn. In phương trình tuyến tính với các hệ số đã nhập dưới dạng: a11x1 a12x2…a1nxn a1n+1 a21x1 a22x2…a2nxn a2n+1 … an1x1 an2x2…annxn ann+1 Với n là số ẩn số được nhập từ bàn phím BT 3a: Viết chương trình tính: giá trị trung bình, giá trị cực đại, giá trị cực tiểu của 1 chuỗi số liệu đã cho trong hai trường hợp: (a) chuỗi số liệu được nhập từ bàn phím; (b) chuỗi số liệu được nhập từ file. BT 3b: Viết lại chương trình như bài tập 3, bằng cách sử dụng các thư viện sẵn có của Fortran (trung bình, cực đại, cực tiểu) BT 4: Viết chương trình sắp xếp một chuỗi số liệu đã cho từ nhỏ tới lớn và ngược lại (từ lớn tới nhỏ). Với chuỗi số liệu được nhập từ: (a) Bàn Phím (b) File BT (lớn): Từ 1 file dữ liệu của khí áp kế (Barometer), tính: (a) Trung bình bình chạy 5 điểm, ghi vào file mới thay giá trị cũ thành các giá trị mới vừa tính (b) Tính trung bình ngày nhiệt độ không khí (Ta) và khí áp (Pa) (c) Tính các giá trị cực đại cực tiểu trong trong ngày của các giá trị Ta, Pa (kết quả tính toán được ghi ra file)