25/05/2018, 10:13

Chương trình con loại hàm

Khi xây dựng chương trình giải một bài toán tương đối phức tạp, ta sẽ thấy chương trình thường dài và khó đọc. Nhiều khi cùng một số thao tác như nhau được thực hiện lặp lại ở một số chỗ trong một chương trình cũng làm cho chương trình của chúng ta trở ...

Khi xây dựng chương trình giải một bài toán tương đối phức tạp, ta sẽ thấy chương trình thường dài và khó đọc. Nhiều khi cùng một số thao tác như nhau được thực hiện lặp lại ở một số chỗ trong một chương trình cũng làm cho chương trình của chúng ta trở thành dài hơn. Những vấn đề này có thể khắc phục bằng cách sử dụng những chương trình con (subprogram) - là một nhóm các lệnh được tách riêng ra và sau đó sẽ được gọi thực hiện khi cần trong chương trình của chúng ta. Trong Fortran có hai loại chương trình con: chương trình con loại hàm (function) và chương trình con loại thủ tục (subroutine). Trong mục 2.4 chương 2 đã giới thiệu và thỉnh thoảng trong các bài khác chúng ta đã sử dụng một vài hàm chuẩn hay hàm riêng của Fortran. Thí dụ, khi tính sin của một góc ta dùng hàm SIN, khi cần giá trị tuyệt đối của một đại lượng ta dùng hàm ABS... Những hàm này thực chất cũng là những chương trình con, nhưng chúng đã được xây dựng sẵn (hàm chuẩn) và nằm trong bộ biên dịch, chúng ta chỉ việc gọi trực tiếp trong chương trình khi cần. Trong chương này sẽ tóm tắt về những đặc điểm của các hàm chuẩn. Sau đó ta học cách tự xây dựng những chương trình con loại hàm để giải quyết những bài toán riêng của mình. Những chương trình con loại thủ tục sẽ xét trong chương 9.

Một hàm tính ra một giá trị, thí dụ căn bậc hai của một số hay giá trị trung bình của một mảng. Fortran có rất nhiều hàm chuẩn (xem danh sách các hàm chuẩn trong phụ lục 1).

Những đặc điểm chính của các hàm chuẩn là:

1) Tên hàm và các giá trị đầu vào (các đối số) cùng thể hiện một giá trị.

2) Một hàm không thể được sử dụng ở vế trái của dấu = trong một lệnh gán.

3) Tên của hàm chuẩn xác định kiểu dữ liệu của đầu ra của hàm. Thí dụ, nếu tên bắt đầu bằng một trong các chữ cái từ I đến N thì giá trị hàm là số nguyên.

4) Các đối số của hàm thường cùng kiểu như hàm, trừ một số ngoại lệ (xem phụ lục 1).

5) Các đối số của một hàm phải nằm trong cặp dấu ngoặc đơn.

6) Các đối số của một hàm có thể là các hằng, biến, biểu thức hay các hàm khác.

7) Các hàm tự sinh (generic function) chấp nhận nhiều kiểu đối số và trả lại giá trị hàm cùng kiểu với đối số. (Thí dụ hàm ABS(X) nếu đối số X là số nguyên thì giá trị hàm ABS(X) cho ra giá trị tuyệt đối là số nguyên, nếu X thực thì giá trị hàm sẽ là thực.)

Thí dụ 22: Đọc từ bàn phím một số nguyên. Kiểm tra xem nó là số chẵn hay số lẻ và in ra thông báo thích hợp. Ta có thể sử dụng hàm chuẩn MOD (I, J) trong bài tập này. Hàm MOD có hai đối số nguyên I và J. Hàm này trả về số dư của phép chia I/J. Vậy chương trình giải bài tập này có thể như sau:

PRINT *, ' NHAP MOT SO NGUYEN '
READ *, K
IF (MOD (K, 2) .EQ. 0) THEN
PRINT 5, K
ELSE
PRINT 8, K
END IF
5 FORMAT (1X, I5, ' LA SO CHAN')
8 FORMAT (1X, I5, ' LA SO LE')

Trong thực tế lập trình giải các bài toán khoa học kỹ thuật nhiều khi đòi hỏi những hàm chưa có trong danh sách các hàm chuẩn của Fortran. Nếu tính toán hay lặp lại thường xuyên và đòi hỏi một số bước, ta nên thực hiện như là một hàm thay vì mỗi lần cần lại phải viết ra các lệnh tính toán. Fortran cho phép chúng ta tự xây dựng những hàm của riêng mình theo hai cách: hàm lệnh (statement function) và hàm chương trình con (function subprogram). Nếu tính toán có thể viết trong một lệnh gán duy nhất, thì ta sử dụng hàm lệnh; ngược lại, nếu phải thực hiện nhiều tính toán hay thao tác mới dẫn tới một giá trị kết quả, thì ta dùng hàm chương trình con.

Hàm lệnh

Dạng tổng quát của hàm lệnh là

Tên hàm (Danh sách đối số) = Biểu thức

Những quy tắc phải tuân thủ khi viết và dùng hàm lệnh:

1) Hàm lệnh được định nghĩa ở đầu chương trình, cùng với các lệnh khai báo kiểu dữ liệu.

2) Định nghĩa hàm lệnh gồm tên của hàm, sau đó đến các đối số nằm trong cặp dấu ngoặc đơn ở vế bên trái của dấu bằng; biểu thức tính giá trị hàm ở vế bên phải của dấu bằng.

3) Tên hàm có thể khai báo trong lệnh khai báo kiểu; nếu không thì kiểu của hàm sẽ được xác định theo cách định kiểu ẩn.

Thí dụ 23: Diện tích của tam giác có thể tính theo hai cạnh và góc xen giữa chúng:

DiÖn tÝch=0,5×c¹nh 1×c¹nh 2 × sin (gãc) size 12{ bold "DiÖn tÝch"="0,5" times bold "c¹nh 1" times bold "c¹nh 2 " times " sin " ( "gãc" ) } {}.

Viết chương trình đọc độ dài ba cạnh của một tam giác và các góc đối diện mỗi cạnh. Tính và in diện tích của tam giác theo ba phương án: trong mỗi phương án sử dụng một cặp cạnh và góc tương ứng.

Trong bài tập này ta phải tính diện tích tam giác ba lần, do đó có thể dùng hàm lệnh để tính diện tích tam giác. Chương trình có thể như sau:

PROGRAM DTTG
REAL CA, CB, CC, A, B, C, DT, DT1, DT2, DT3,
* C1, C2, GOC
DT (C1, C2, GOC) = 0.5 * C1 * C2 * SIN (GOC)
PRINT *, ' Nhap ba canh tam giac theo thu tu sau:'
PRINT *, ' Canh A Canh B Canh C'
READ *, CA, CB, CC
PRINT *, ' Nhap ba goc (radian) theo thu tu sau:'
PRINT *, ' Doi dien: canh A canh B canh C'
READ *, A, B, C
DT1 = DT (CB, CC, A)
DT2 = DT (CC, CA, B)
DT3 = DT (CA, CB, C)
PRINT *
PRINT *, 'Cac dien tich tinh theo ba phuong an la:'
PRINT 5, DT1, DT2, DT3
5 FORMAT (1X, 3F7.2)
END

Nhận xét rằng trong chương trình này hàm tính diện tích tam giác được định nghĩa ở đầu chương trình bởi tên DT và ba đối số hình thức C1, C2, GOC và giá trị của hàm được tính chỉ bằng một lệnh gán (dòng lệnh thứ ba). Trong chương trình, ở các dòng lệnh thứ 10-12 ta gọi hàm ba lần, mỗi lần ta chuyển các biến khác nhau vào vị trí của các đối số hình thức. Kiểu dữ liệu của hàm DT được mô tả tường minh tại lệnh mô tả REAL ở đầu chương trình. Trong chương trình chính các góc được cho bằng rađian. Nếu các góc nhập vào được cho bằng độ và để không cần chuyển đổi thành rađian trước khi gọi hàm DT tính các diện tích, ta có thể định nghĩa lại hàm DT như sau:

DT(C1, C2, GOC) = 0.5*C1*C2*SIN (GOC * 3.14159 / 180.0)

Hàm chương trình con

Thực chất của hàm chương trình con là một hàm do người lập trình tự xây dựng, do đó người ta còn gọi là hàm do người dùng định nghĩa. Hàm loại này khác với hàm lệnh ở chỗ nó được tính không phải bằng một lệnh gán duy nhất mà bằng một số lệnh. Hàm chương trình con bắt đầu với lệnh không thực hiện để đặc tả hàm bằng một tên và một danh sách đối số như sau

FUNCTION Tên hàm (danh sách đối số)

Sau các lệnh mô tả và tính toán, lệnh RETURN chuyển điều khiển về chương trình chính và lệnh END báo cho chương trình dịch sự kết thúc của chương trình con. Tên hàm được chọn theo quy tắc như tên hằng, tên biến của Fortran. Tên hàm có ý nghĩa mô tả ẩn kiểu giá trị của hàm nếu trong chương trình chính chưa khai báo tường minh. Trong danh sách đối số nếu có từ hai đối số trở lên thì các đối số cách nhau bởi dấu phảy. Tên các đối số cũng có ý nghĩa mô tả ẩn kiểu dữ liệu của đối số. Tuy nhiên, nên mô tả tường minh các đối số của hàm trong phần khai báo các biến của hàm. Trong phần khai báo này, ngoài các đối số còn có thể khai báo các biến khác được dùng chỉ trong nội bộ hàm chương trình con. Vậy hình dáng tổng quát của một hàm chuơng trình con như sau:

FUNCTION Tên (đối số 1, đối số 2, ...)

Các lệnh mô tả các đối số, các biến cục bộ

Các lệnh thực hiện

RETURN

END

Các hàm chương trình con được viết tách ra khỏi chương trình chính và nằm sau lệnh END của chương trình chính. Trong chương trình chính, khi cần tới hàm con người ta thường dùng lệnh gán để gán giá trị tính được bởi hàm con vào một biến hoặc dùng trực tiếp tên hàm con trong các biểu thức. Những giá trị của các đối số thực tế gửi vào các đối số hình thức phải phù hợp về kiểu và đúng tuần tự như trong danh sách đối số. Ta xét thí dụ về xây dựng hàm con và cách dùng nó trong chương trình chính qua thí dụ 24 dưới đây.

Thí dụ 24: Các mô hình số thường tính ra các giá trị của các thành phần kinh hướng Vk size 12{V rSub { size 8{k} } } {} và vĩ hướng Vv size 12{V rSub { size 8{v} } } {} của tốc độ gió ở những điểm khác nhau. Từ những cặp giá trị thành phần kinh hướng và vĩ hướng cần tính ra tốc độ V size 12{V} {} và hướng gió d size 12{d} {}. Tốc độ gió tính bằng công thức

V=Vk2+Vv2 size 12{V= sqrt {V rSub { size 8{k} } rSup { size 8{2} } +V rSub { size 8{v} } rSup { size 8{2} } } } {},

còn hướng gió (góc giữa vectơ gió và hướng bắc) tính theo công thức

α nÕu V v ≥ 0, V k > 0 180 − α nÕu V v ≥ 0, V k < 0 180 + α nÕu V v < 0, V k < 0 360 − α nÕu V v < 0, V k > 0 d = { { { size 12{d=alignl { stack { left lbrace α" nÕu "V rSub { size 8{v} } >= 0," "V rSub { size 8{k} } >0 {} # right none left lbrace "180" - α" nÕu "V rSub { size 8{v} } >= 0," "V rSub { size 8{k} } <0 {} # right none left lbrace "180"+α" nÕu "V rSub { size 8{v} } <0," "V rSub { size 8{k} } <0 {} # right none left lbrace "360" - α" nÕu "V rSub { size 8{v} } <0," "V rSub { size 8{k} } >0" " {} # right no } } lbrace } {}

trong đó α=180πarctg ∣VvVk∣ size 12{α= { {"180"} over {π} } "arctg " lline { {V rSub { size 8{v} } } over {V rSub { size 8{k} } } } rline } {}.

Giả sử các giá trị của các thành phần kinh hướng và vĩ hướng của tốc độ gió đã lưu trong file GIOKV.KQ1 thành hai cột, dòng đầu tiên của file ghi số dòng dữ liệu có trong file. Viết chương trình đọc file GIOKV.KQ1 và ghi kết quả tính tốc độ và hướng gió vào file mới GIO.KQ2 thành 4 cột dạng sau:

TT Vk size 12{V rSub { size 8{k} } } {}Vv size 12{V rSub { size 8{v} } } {} m/s HUONG

XX XX.X XX.X XXX XXX

XX XX.X XX.X XXX XXX

. . .

Khi lập chương trình giải quyết nhiệm vụ này ta nhận thấy cần tính mô đun của tốc độ gió và hướng gió nhiều lần. Vậy có thể sử dụng các hàm, ngoài ra, để tính tốc độ gió có thể dùng loại hàm lệnh, để tính hướng gió dùng hàm chương trình con. Chương trình có thể như sau:

REAL GIOK (200), GIOV (200), V, H, TOCDO, HUONG
INTEGER I, N
C Mô tả hàm lệnh tính mô đun tốc độ gió
TOCDO (VK, VV) = SQRT (VK*VK+VV*VV)
OPEN (1, FILE = 'GIO.KQ1', STATUS = 'OLD')
READ(1,*) N
DO I = 1, N
READ(1,*) GIOK (I), GIOV (I)
END DO
CLOSE (1)
OPEN (1, FILE = 'GIO.KQ2', STATUS = 'UNKNOWN')
WRITE (1, 4) ‘TT’, ‘VK’, ‘VV’, ‘M/S’, ‘HUONG’
4 FORMAT(1X, I3, 4F7.1)
DO I = 1, N
V = TOCDO (GIOK (I), GIOV (I))
H = HUONG (GIOV (I), GIOK (I))
WRITE (1, 5) I, GIOK (I), GIOV (I), V, H
5 FORMAT (1X, I3, 4F7.1)
END DO
END
C Hàm chương trình con
FUNCTION HUONG (VV, VK)
REAL VV, VK, HG
IF (VK .EQ. 0.0) THEN
IF (VV .GE. 0.0) THEN
HG = 90.0
ELSE
HG = 270.0
ENDIF
ELSE
G = ATAN (ABS (VV / VK)) / 3.14159 * 180.0
IF (VK .GT. 0.0) THEN
IF (VV .GE. 0.0) THEN
HG = G
ELSE
HG = 360.0 - G
ENDIF
ELSE
IF (VV .GE. 0.0) THEN
HG = 180.0 - G
ELSE
HG = 180.0 + G
ENDIF
ENDIF
ENDIF
HUONG = HG
RETURN
END

Trong thí dụ này, ta thấy việc tính mô đun tốc độ và hướng được thực hiện nhiều lần. Do đó đã tổ chức tính chúng trong các hàm. Vì giá trị mô đun tính đơn giản bằng một biểu thức nên đã dùng loại hàm lệnh, đó là hàm TOCDO được định nghĩa ở dòng lệnh thứ ba của chương trình chính. Việc tính hướng phải thực hiện nhờ một số phép tính và thao tác, do đó đã dùng loại hàm chương trình con HUONG. Kiểu dữ liệu của hai hàm này được khai báo tường minh ở phần khai báo trong chương trình chính.

Thí dụ 25: Ước lượng nghiệm của đa thức bậc 4

f ( x ) = a 0 + a 1 x + a 2 x 2 + a 3 x 3 + a 4 x 4 size 12{f ( x ) =a rSub { size 8{0} } +a rSub { size 8{1} } x+a rSub { size 8{2} } x rSup { size 8{2} } +a rSub { size 8{3} } x rSup { size 8{3} } +a rSub { size 8{4} } x rSup { size 8{4} } } {}

trên khoảng [-5, 5].

Để giải bài toán này, ta sử dụng hai phương pháp tìm nghiệm của phương trình là phương pháp tìm hẹp dần và phương pháp chia đôi.

Trong phương pháp tìm hẹp dần, miền tìm nghiệm được chia thành những khoảng đủ nhỏ sao cho thực tế có thể xem rằng trong một khoảng nào đó chỉ có một nghiệm. Xét các khoảng từ trái sang phải, ta sẽ tìm những chỗ mà đồ thị của đa thức cắt trục x size 12{x} {}: bằng cách tính các giá trị của đa thức tại các đầu mút của khoảng, nếu dấu của các giá trị của đa thức tại các đầu mút khác nhau, thì đồ thị cắt trục x size 12{x} {} và ít nhất có một nghiệm trong khoảng đó. Sau đó khoảng chứa nghiệm lại được chia tiếp thành các phụ khoảng nhỏ hơn và quá trình tìm lại bắt đầu từ đầu trái cho đến khi xác định được khoảng chứa nghiệm. Quá trình chia khoảng và tìm lặp lại cho đến khi nghiệm được xác định đủ độ chính xác.

Phương pháp chia đôi bắt đầu với một khoảng đã được biết là chứa một nghiệm. Khác với phương pháp tìm hẹp dần chia khoảng chứa nghiệm thành nhiều phụ khoảng trước khi tìm, phương pháp chia đôi chỉ chia khoảng chứa nghiệm thành hai nửa, sau đó xác định nửa nào chứa nghiệm. Sự chia đôi tiếp tục cho đến khi tìm được nghiệm với độ chính xác mong muốn.

Trong thí dụ này, ta kết hợp hai phương pháp: phương pháp tìm hẹp dần để xác định khoảng chứa nghiệm. Sau đó phương pháp chia đôi xác định nghiệm với độ chính xác cần thiết. Giả sử phương pháp chia đôi tiếp tục lặp cho đến khi nửa khoảng nhỏ hơn 0,01 và nghiệm tìm được nếu giá trị tuyệt đối của đa thức không lớn hơn 0,001.

INTEGER I, N
REAL A (0 : 4)
REAL TRAI, PHAI, GIUA, KHOANG, NGHIEM
LOGICAL XONG
PRINT * , ' NHAP CAC HE SO A0, A1, A2, A3, A4 '
READ*, A
PRINT 5, A
5 FORMAT (/, ' DA THUC:'
* / 1X, 9X, '4', 11X, '3', 11X, '2' / 1X, 4(F7.3, ' X + '), F7.3)
N = 0
DO I = 1, 40
TRAI = -5.0 + REAL (I-1) * 0.25
PHAI = TRAI + 0.25
IF (ABS(F(A, TRAI)) .LT. 0.001) THEN
PRINT 15, TRAI, F(A, TRAI)
15 FORMAT (1X, 'NGHIEM = ', F7.3, 3X,
* 'F(NGHIEM) = ', F7.3)
N = N + 1
ELSE IF (F(A, TRAI)*F(A, PHAI) .LT. 0.0) THEN
XONG = .FALSE.
KHOANG = PHAI - TRAI
20 IF (KHOANG .GT. 0.01 .AND. .NOT. XONG) THEN
GIUA = 0.5 *(TRAI + PHAI)
IF (ABS (F(A, GIUA)) .LT. 0.001) THEN
XONG = .TRUE.
ELSE IF (F(A, GIUA)*F(A, TRAI) .LT. 0.0) THEN
PHAI = GIUA
ELSE
TRAI = GIUA
END IF
KHOANG = PHAI - TRAI
GOTO 20
END IF
IF (KHOANG .GT. 0.01) THEN
NGHIEM = GIUA
ELSE
NGHIEM = 0.5 *(TRAI + PHAI)
END IF
PRINT 15, NGHIEM, F(A, NGHIEM)
N = N + 1
END IF
END DO
TRAI = 5.0
IF (ABS (F (A, TRAI)) .LT. 0.001) THEN
PRINT 15, TRAI, F (A, TRAI)
N = N + 1
END IF
IF (N .EQ. 0) THEN
PRINT *, ' KHONG NGHIEM TRONG KHOANG [-5,5]'
END IF
END
REAL FUNCTION F (A, X)
REAL A(0 : 4), X
F=A(0) + A(1)*X + A(2)*X**2 + A(3)*X**3 + A(4)*X**4
RETURN
END

Trong chương trình này, ta đã chia miền tìm nghiệm [-5, 5] thành 40 khoảng, mỗi khoảng dài 0,25 và thực hiện việc kiểm tra từ trái sang phải xem trong những khoảng nào có thể có nghiệm bằng phương pháp tìm hẹp dần bằng vòng DO. Trong mỗi khoảng, nếu giá trị đa thức ở đầu mút trái của khoảng không khác không quá 0,001 thì nhận nghiệm bằng đầu mút trái và chuyển sang xét khoảng tiếp sau ở bên phải. Còn nếu giá trị đa thức ở hai đầu mút của khoảng đang xét khác dấu, thì ta tìm nghiệm theo phương pháp chia đôi. Quá trình lặp để liên tiếp chia đôi khoảng thực hiện bằng vòng lặp IF lôgic và lệnh GOTO vô điều kiện cho đến khi khoảng trở nên nhỏ hơn hoặc bằng 0,01 hoặc giá trị tuyệt đối của đa thức ở giữa khoảng không lớn hơn 0,001. Việc tính giá trị đa thức thực hiện nhiều lần với những giá trị x size 12{x} {} khác nhau nên ta đã tổ chức hàm F để chuyên làm việc này.

Thí dụ 26: Viết chương trình đọc liên tiếp từ bàn phím ba số nguyên, kiểm tra xem chúng có tuần tự chỉ ngày tháng năm hợp lý không và in ra thông báo phù hợp. Chương trình kết thúc khi ta nhập ngày tháng năm đều là những số không.

PROGRAM KTNGAY
INTEGER ID, IM, IY
10 PRINT *, 'HAY NHAP BA SO NGUYEN'
READ *, ID, IM, IY
IF (ID .NE. 0 .AND. IM .NE. 0 .AND. IY .NE. 0) THEN
IF (OKDATE (ID, IM, IY)) THEN
PRINT*, 'CO THE LA NGAY THANG NAM HOP LY'
ELSE
PRINT*, ‘KHONG THE LA ’,
* ‘NGAY THANG NAM HOP LY’
ENDIF
GOTO 10
ENDIF
END
INTEGER FUNCTION SNTT (M, Y)
INTEGER M,Y
IF (M. EQ. 2) THEN
SNTT = 28
IF ((MOD (Y,100) .NE. 0 .AND. MOD (Y,4) .EQ. 0) .OR.
* (MOD (Y,100) .EQ. 0 .AND. MOD (Y/100, 4) .EQ .0))
* SNTT = 29
ELSE IF (M.EQ.4 .OR. M.EQ.6 .OR. M.EQ.9 .OR. M.EQ.11) THEN
SNTT = 30
ELSE
SNTT = 31
ENDIF
RETURN
END
LOGICAL FUNCTION OKDATE (D, M, Y)
INTEGER D,M,Y,NNGAY
IF (D.LT.1.OR.D.GT.31.OR.M.LT.1.OR.M.GT.12) THEN
OKDATE = .FALSE.
ELSE
NNGAY = SNTT (M, Y)
OKDATE = D.LE.NNGAY
ENDIF
RETURN
END

Trong chương trình này dùng hai hàm con: hàm OKDATE và hàm SNTT. Hàm OKDATE có ba đối số nguyên D, M, Y và đưa ra giá trị lôgic là .TRUE. nếu D, M, Y là những số nguyên chỉ ngày tháng hợp lý. Hàm SNTT có hai đối số nguyên và đưa ra giá trị nguyên là số ngày của tháng đang xét. Nhận thấy rằng chương trình chính gọi hàm con OKDATE, về phần mình hàm con OKDATE trong khi thực hiện lại gọi hàm con SNTT.

Kiểm tra sự làm việc đúng đắn của hàm tự xây dựng cũng giống như kiểm tra chương trình chính. Nên thử cho hàm con những giá trị đối số khác nhau xem nó có đưa ra giá trị hàm đúng đắn không. Nếu hàm con làm việc không đúng đắn, hãy kiểm tra những điểm sau:

1) Sự phù hợp về kiểu và thứ tự của đối số thực tế và đối số hình thức.

2) Khẳng định rằng trước lệnh RETURN hàm đã nhận một giá trị đúng.

3) In kiểm tra giá trị các đối số trước và sau khi gọi hàm con.

4) Có thể dùng lệnh PRINT trong hàm con để định vị chỗ lỗi trong hàm con.

Sử dụng hàm lệnh và hàm chương trình con sẽ làm chương trình có tính cấu trúc hơn và dễ đọc. Trong chương trình con cũng nên có cấu trúc sáng rõ. Nếu hàm dài và khó đọc, hãy dùng hàm con khác trong hàm con. Một khi bạn quyết định dùng hàm con, hãy cân nhắc những điều sau đây:

1) Chọn tên hàm con sao cho tên có tính gợi nhớ.

2) Nên dùng tên các đối số hình thức trong hàm con trùng với tên của các đối số thực tế. Nếu hàm được dùng nhiều lần với những đối số thực tế khác nhau, thì hãy chọn tên đối số hình thức hoàn toàn khác để tránh sự nhầm lẫn với các biến của chương trình chính. Có thể cách sau đây là một cách nên được dùng: tên các đối số trong hàm con đặt bằng các từ tiếng Anh, còn tên các đối số thực tế - bằng các từ tương ứng của tiếng Việt.

Bài tập

1. Viết chương trình in giá trị các biểu thức sau:

α = 6,9 + y y 2 + 1 + 2y + 3y 2 β = sin y y 4 + 1 + 2y 2 + 3y 4 alignl { stack { size 12{α= { {6,9+y} over {y rSup { size 8{2} } + sqrt {1+2y+3y rSup { size 8{2} } } } } } {} # β= { {"sin"y} over {y rSup { size 8{4} } + sqrt {1+2y rSup { size 8{2} } +3y rSup { size 8{4} } } } } {} } } {}
γ = 2,3 z + z 4 z 2 + 1 + 2z + 3z 2 δ = 1 sin 2 y + 1 + 2 sin y + 3 sin 2 y alignl { stack { size 12{γ= { {2,3z+z rSup { size 8{4} } } over {z rSup { size 8{2} } + sqrt {1+2z+3z rSup { size 8{2} } } } } } {} # δ= { {1} over {"sin" rSup { size 8{2} } y+ sqrt {1+2"sin"y+3"sin" rSup { size 8{2} } y} } } {} } } {}

trong chương trình hãy xây dựng hàm con tên là DENOM với đối số x size 12{x} {} chuyên để tính biểu thức

x2+1+2x+3x2 size 12{x rSup { size 8{2} } + sqrt {1+2x+3x rSup { size 8{2} } } } {}.

2. Hãy cải tiến chương trình tìm nghiệm của đa thức ở thí dụ 25 trang 139 sao cho nó cho phép người dùng nhập khoảng xác định nghiệm thay vì dùng khoảng [-5, 5].

3. Hãy cải tiến chương trình tìm nghiệm của đa thức ở thí dụ 25 trang 139 sao cho nó cho phép người dùng nhập kích thước của phụ khoảng trong phần tìm hẹp dần.

4. Viết hàm chương trình con nhận giá trị một số nguyên và trả về giai thừa của số nguyên đó.

5. Côsin của một góc tính theo công thức chuỗi

cos x = 1 − x 2 2 ! + x 4 4 ! − x 6 6 ! + . . . size 12{"cos"x=1 - { {x rSup { size 8{2} } } over {2 !} } + { {x rSup { size 8{4} } } over {4 !} } - { {x rSup { size 8{6} } } over {6 !} } + "." "." "." } {}

trong đó x size 12{x} {} tính bằng rađian. Hãy viết hàm chương trình con COSX với đầu vào là góc tính bằng độ, tính ra côsin của góc đó với độ chính xác ≤ 0,000001, sử dụng hàm con tính giai thừa ở bài tập 4. Sau đó viết chương trình chính in bảng ba cột: cột thứ nhất ( x size 12{x} {}) chứa góc từ 0 đến 360° với gia số 15°; cột thứ hai chứa côsin của góc tính theo hàm chuẩn COS của Fortran và cột thứ ba chứa côsin tính theo hàm con COSX.

6. Viết hàm chương trình con MEDIAN (X,N) với đầu vào là mảng REAL X(N) đã sắp xếp tăng hoặc giảm dần và số giá trị thực tế của mảng N, trả về giá trị của trung vị của chuỗi x(n) size 12{x ( n ) } {} theo định nghĩa:

- nếu n size 12{n} {} lẻ trung vị bằng xn2+1 size 12{x left ( { {n} over {2} } +1 right )} {},

- nếu n size 12{n} {} chẵn trung vị bằng x(n/2)+x(n/2+1)2 size 12{ { {x ( n/2 ) +x ( n/2+1 ) } over {2} } } {}.

7. Viết hàm chương trình con DAD (D1, M1, Y1, D2, M2, Y2) với 6 đối số hình thức kiểu số nguyên: D1, M1, Y1, D2, M2, Y2 lần lượt chỉ ngày, tháng, năm của hai ngày bất kỳ. Hàm này sẽ có giá trị lôgic bằng TRUE nếu ngày D2, M2, Y2 là ngày muộn hơn ngày D1, M1, Y1, còn nếu không thì nó sẽ có giá trị FALSE. Sau đó hãy viết một chương trình chính cho phép ta nhập từ bàn phím một ngày bất kỳ trong quá khứ hoặc trong tương lai, xác định và in lên màn hình thứ trong tuần của ngày đó. Biết rằng ngày 1-1-2001 là ngày thứ hai.

0