Điều kiện condition được kiểm tra ngay tại đầu mỗi vòng lặp, nếu nó thỏa mãn giá trị của nó là đúng thì các câu lệnh bên trong được thực hiện, sau đó lại tiếp tục kiểm tra điều kiện cond
Trang 1Chương 4
Lập trình trên Maple
4.1 Các lệnh lập trình cơ bản 127
4.1.1 Vòng lặp while 129
4.1.2 Vòng lặp for 130
4.1.3 Lệnh điều kiện if 132
4.1.4 Lệnh break 136
4.1.5 Lệnh next 137
4.2 Thiết lập một chu trình (Procedure) 138
4.2.1 Giới thiệu 138
4.2.2 Khai báo chu trình 138
4.2.3 Tham biến 139
4.2.4 Phạm vi các biến (biến toàn cục, biến cục bộ và tham biến) 140
Biến toàn cục 140
Biến cục bộ 140
Tham biến 141
4.2.5 Định giá trên các biến 141
Định giá tên hàm và tham biến 141
Định giá biến cục bộ và biến toàn cục 142
Minh hoạ 142
4.2.6 Xử lý các chu trình đệ qui (tuỳ chọn remember) 143
Chạy từng bước chu trình 144
Ví dụ 146
4.2.7 Sử dụng các hàm RETURN, ERROR 148
Trang 24.2.8 Một số ví dụ về chu trình 149
1 Chu trình tìm các thành phần tối đại trong một mảng 149
2 Chu trình tính khai triển Fourier của hàm số 151
4.3 Tìm lỗi trong chu trình 154
4.3.1 Printlevel (Lần theo các bước của chu trình) 154
4.3.2 Trace (dò từng lệnh trong chu trình) 157
4.3.3 Xem mã nguồn một chu trình 158
4.3.4 Xem một chu trình bằng lệnh print 161
4.3.5 Chặn bắt lỗi 161
4.4 Làm việc trên các tệp trong Maple 164
4.4.1 Các thao tác cơ bản 164
Mở một tệp 164
Đóng một tệp đã được mở 166
Xác định vị trí cuối tệp 166
Lấy và đặt lại vị trí hiện thời trong tệp 168
Xoá một tệp 169
Đẩy dữ liệu từ vùng đệm vào đĩa 170
Mở một tệp để đọc/ghi mà không dùng vùng đệm 171
Đóng tệp được mở không dùng vùng nhớ đệm 173
Lệnh ghi dữ liệu 174
Lệnh đọc dữ liệu read 175
4.4.2 Đọc dữ liệu từ tệp vào 176
Đọc một dòng từ tệp 176
Đọc một số bytes từ tệp 177
Đọc lệnh từ bàn phím 178
Đọc dữ liệu có số cột và kiểu cố định 179
Đọc dữ liệu định rõ kiểu 180
4.4.3 Ghi dữ liệu vào tệp 181
Giao diện của công việc ghi 181
Ghi bằng lệnh in (print) 182
Lệnh lprint() 183
4.4.4 Ví dụ về thao tác trên tệp 184
Trang 3Vòng lặp while cho phép lặp chuỗi các câu lệnh nằm giữa do và od khi mà
điều kiện condition vẫn còn đúng (tức là biểu thức điều kiện cho giá trị true)
Điều kiện condition được kiểm tra ngay tại đầu mỗi vòng lặp, nếu nó thỏa mãn (giá trị của nó là đúng) thì các câu lệnh bên trong được thực hiện, sau đó lại tiếp tục kiểm tra điều kiện condition cho đến khi điều kiện không còn thỏa mãn nữa.Vòng lặp while thường được sử dụng khi số lần lặp một hay một chuỗi biểu thức là không xác định rõ, đồng thời ta muốn các biểu thức đó cần được lặp trong khi một điều kiện nào đó còn được thỏa mãn
Điều kiện condition trong vòng lặp phải là một biểu thức boolean, tức là
giá trị của nó chỉ có thể là đúng hoặc sai, nếu không thì sẽ sinh ra lỗi
Trong trường hợp muốn thoát ra khỏi vòng lặp ngay từ trong giữa vòng lặp, ta
có thể thực hiện bằng cách dùng câu lệnh RETURN, break hoặc quit
Chú ý rằng vòng lặp while-do-od; không bắt buộc phải nằm trên nhiều dòng lệnh nhưng người ta thường viết trên nhiều dòng để câu lệnh dễ đọc và dễ hiểu hơn
Minh hoạ
Tìm ước số chung lớn nhất của 2 số nguyên theo thuật toán Eulid
Tư tưởng của thuật toán:
- Khai báo 2 số a,b
- Tìm phần dư trong phép chia của a cho b , gọi đó là d
- Sau đó đặt a:=b (cho a mang giá trị của b ), và tương tự b:=d
- Vòng lặp cứ tiếp tục cho đến khi b=0 (Tức lúc đó phần dư bằng
0 )
Vì không xác định trước số vòng phải lặp, ta dùng vòng lặp không xác định (While)
[>a:=20;b:=15;
Trang 4- od: có nghĩa là chỉ in ra kết quả cuối cùng
In ra 11 số liên tiếp trong dãy số Fibonacci , từ số thứ 5 đến số thứ 15
Dãy số này có tính chất số sau bằng tổng 2 số ngay trước nó (kể từ số thứ 3 trở
đi) Cụ thể là nó được xác định như sau :
= ( )
Trang 5Vòng lặp for được dùng để lặp một chuỗi các biểu thức được đặt giữa do và od
, mỗi lần lặp tương ứng với một giá trị phân biệt của biến chỉ số name đứng sau từ
khoá for Ban đầu, giá trị start được gán cho biến chỉ số Nếu giá trị của biến name
nhỏ hơn hay bằng giá trị finish thì chuỗi lệnh nằm giữa do và od được thực hiện,
sau đó biến name được gán giá trị tiếp theo bằng cách cộng thêm vào nó giá trị
change (name:=name+change) Sau đó, biến name được so sánh với finish để
quyết định xem việc thực hiện chuỗi lệnh có được tiếp tục nữa không Quá trình so
sánh biến chỉ số name và thực hiện chuỗi lệnh được lặp liên tiếp cho đến khi giá trị của biến name lớn hơn giá trị finish Giá trị cuối cùng của biến name sẽ là giá trị vượt quá finish đầu tiên
Chú ý: nếu các từ khóa from start hoặc by change bị bỏ qua thì mặc định from
1 và by 1 được dùng
Vòng lặp for-in-do-od thực hiện việc lặp với mỗi giá trị mà biến chỉ số
name lấy từ biểu thức expression đã cho Chẳng hạn vòng lặp này được sử dụng
hiệu quả khi mà giá trị của biến name là một phần tử của một tập hợp hoặc danh
sách
Trong trường hợp muốn thoát khỏi từ giữa vòng lặp, ta có thể dùng các câu lệnh
break,quit,RETURN giống như trong vòng lặp while
od;
od;
print(a);
Trang 614
151
3
14
15
161
4
15
16
171
5
16
17
18
2) Cho một danh sách các số nguyên Tính tổng bình phương các số chẵn có mặt
print(`Tong binh phuong cac so chan la :`);tong;
Tong binh phuong cua cac so chan la :
72
4.1.3 Lệnh điều kiện if
Cấu trúc cú pháp:
if condition then statement sequence
| elif condition then statement sequence |
| else statement sequence | fi;
(Ghi chú: Các câu lệnh trong cặp dấu ngoặc đứng là các lệnh tuỳ chọn Thí dụ:
biểu thức | statement | cho biết rằng statement là một câu lệnh tuỳ chọn.)
Trang 7Chức năng:
Nếu bạn muốn một dãy biểu thức được thực hiện khi điều kiện nào đó được thoả mãn và một dãy biểu thức khác được thực hiện nếu trái lại thì có thể dùng câu lệnh if-then-else-fi Trong câu lệnh trên, nếu điều kiện condition là đúng thì chuỗi biểu thức đứng sau then được thực hiện, nếu trái lại thì điều kiện condition sau từ khoá elif sẽ được kiểm tra, nếu nó đúng thì chuỗi lệnh tương ứng sau then
được thực hiện, cứ tiếp tục cho đến khi các điều kiện condition đều không thỏa mãn, thì các biểu thức sau lệnh else được thực hiện
Lưu ý rằng cấu trúc lệnh (tuỳ chọn) elif then được lặp lại với số lần tuỳ
ý Từ khoá elif là dạng viết tắt của else if
Các biểu thức điều kiện (condition) được sử dụng trong câu lệnh if phải được tạo
thành từ các bất đẳng thức, các đẳng thức ( các phép toán quan hệ ), các biến số, các phép toán logic, các hàm có giá trị trả lại là giá trị logic Nếu trái lại thì sẽ gây
Chú ý: Nếu chưa có sẵn một mảng số ta có thể dùng lệnh tạo số ngẫu nhiên của
Maple (rand(a b)) để sinh một số nguyên nào đó không bé hơn a và không lớn
hơn b Với 10 lần chọn (ngẫu nhiên) ta sinh được một mảng gồm 10 số Sau đó ta
áp dụng thuật toán đã nêu trên để sắp xếp lại mảng này (theo thứ tự tăng dần) [>a:=array(1 10):
Trang 8Tìm phần tử lớn nhất của mảng (hoặc một danh sách)
Cho trước một danh sách ta phải tìm phần tử lớn nhất của danh sách Có thể thực hiện điều này bằng cách sắp xếp lại mảng (theo chu trình đã làm ở trên) và lấy
ra phần tử cuối cùng của mảng (sau khi sắp) Một cách khác là: Gọi M là một phần
tử bất kì của danh sách, sau đó duyệt toàn bộ danh sách nếu phần tử nào của danh sách lớn hơn nó thì lại lấy tên M gán cho phần tử đó, và lặp lại quá trình cho đến khi không còn phần tử nào lớn hơn M
Chú ý Ta dùng lệnh op(i,ds) để lấy ra thành phần thứ i trong danh sách ds,
và dùng lệnh nops(ds) để xác định số lượng các thành phần trong danh sách ds
print(`Gia tri lon nhat cua danh sach la :`); M;
Gia tri lon nhat cua danh sach la :
5
Chu trình giải phương trình bậc hai
= + +
print(`phuong trinh vo nghiem `);
elif delta=0 then
x1:=-b/(2*a);
Trang 9print(`Pt co nghiem kep `,x1);
[>a:=dathucTBS(10):#Goi thu tuc sinh da thuc TBS den bac 10
Trang 10break để nhảy ra khỏi vòng lặp tìm kiếm Trước lệnh break thường có một câu
lệnh điều kiện if then
Nếu lệnh break dùng ngoài các vòng lặp while/for thì sẽ sinh ra lỗi
Chú ý Từ break không phải là từ khoá (từ dành riêng cho Maple), vì vậy ta có thể gán trị cho biến có tên là break mà không hề sinh ra lỗi (mặc dù điều này là không nên)
Minh hoạ
Dùng break để dừng khi gặp phần tử chẵn của mảng (ta duyệt tất cả các phần
tử của mảng nếu gặp phần tử chẵn đầu tiên thì dừng lại )
Trang 11[17 7 15 7 12 4 17 3 19 3, , , , , , , , , ]Phan tu dau tien cua mang la:
12
4.1.5 Lệnh next
Cấu trúc và chức năng
Cũng giống như câu lệnh break, lệnh next được thực hiện trong vòng lặp
while/for với mục đích bỏ qua một số lệnh bên trong vòng lặp để nhảy qua lần
lặp tiếp theo Khi gặp lệnh next trong vòng lặp, chương trình bỏ qua các lệnh tiếp theo của vòng lặp tận cùng nhất chứa next cho đến khi gặp từ khoá xác định kết thúc vòng lặp ( ở đây là lệnh od) Đến đây vòng lặp tiếp tục nhảy qua lần lặp tiếp theo (nếu có thể) bằng cách tăng chỉ số hoặc kiểm tra điều kiện để quyết định xem
có nên thực hiện vòng lặp tiếp theo
Lệnh next sinh ra lỗi nếu nó được gọi ngoài vòng lặp while/for Tương tự như
break, next cũng không phải là từ khóa , do đó ta hoàn toàn có thể gán cho next
một giá trị (xem như next là một biến) Ngay trước lệnh next cũng thường là một câu lệnh điều kiện if then
Trang 12[17 12 20 20 8 11 11 7 2 1 1 19 18 2 18, , , , , , , , , , , , , , ]Tong cac so chan trong mang la:
100
4.2 Thiết lập một chu trình (Procedure)
4.2.1 Giới thiệu
Maple là một ngôn ngữ lập trình hướng chu trình (procedure) Chúng ta có thể làm
việc với Maple bằng hai chế độ khác nhau: Chế độ tương tác trực tiếp thông qua việc nhập từng lệnh đơn lẻ ngay tại dấu nhắc lệnh của Maple và nhận được ngay kết
quả của lệnh đó Chế độ chu trình được thực hiện bằng cách đóng gói một dãy các
lệnh xử lí cùng một công việc vào trong một chu trình (procedure) duy nhất, sau
đó ta chỉ cần gọi chu trình này và Maple tự động thực hiện các lệnh có trong chu trình đó một cách tuần tự và sau đó trả lại kết quả cuối cùng
Maple chứa một lượng rất lớn các hàm tạo sẵn đáp ứng cho những yêu cầu tính toán khác nhau trong nhiều lĩnh vực Các hàm này được lưu trữ trong các gói chu trình (package) và người sử dụng có thể dễ dàng gọi đến mỗi khi cần thiết Tuy nhiên, người dùng Maple có thể tự tạo cho riêng mình những gói chu trình cũng như có thể trao đổi dùng chung những gói chu trình nào đấy, phục vụ cho công việc mang tính
đặc thù riêng của mình
Các khái niệm cơ bản cần phải nắm vững để tạo ra một chu trình ( procedure) là:
Cấu trúc proc() end; cùng với các khai báo trong cấu trúc này (global, local, option, )
Các cấu trúc dữ liệu và các hàm có liên quan (dãy-sequence,tập
hợp-set, danh sách-list, mảng-array, bảng-table)
Các hàm lập trình cơ bản (đã nêu ở trên) và các hàm liên quan đến việc xử lí dữ liệu (eval, evalf, subs, map, convert, )
Các hàm gỡ lỗi và cách bẫy lỗi
4.2.2 Khai báo chu trình
Lời gọi khai báo một chu trình:
Trang 13Giải thích các khai báo:
parameter_name: Là một dãy các kí hiệu, ngăn cách nhau bởi các dấu phẩy, chứa
tên các tham biến truyền cho chu trình
local_sequence: Là một dãy các tên được khai báo là biến cục bộ trong chu trình,
nó chỉ có giá trị sử dụng trong phạm vi chu trình đang xét (local được sử dụng để
khai báo cho các biến chỉ sử dụng bên trong một chu trình)
global_sequen: Dãy các tên biến toàn cục có giá trị sử dụng ngay cả bên ngoài chu
trình
options_sequence: Dãy các tuỳ chọn cho một chu trình
statements_sequence: Dãy các câu lệnh do người lập trình đưa vào
4.2.3 Tham biến
Tham biến (parameter) là các biến được đặt giữa hai dấu ngoặc trong biểu thức
proc( ) Tham biến được dùng để nhận dữ liệu truyền cho chu trình khi gọi
chu trình đó Ví dụ ta có khai báo chu trình tính tổng của 2 số:
tong:=proc(x,y) x+y; end, thì khi gọi chu trình này để tính tổng của hai số
10 và 5 ta phải truyền các dữ liệu này cho các tham biến (cho x nhận giá trị là 10,
y nhận giá trị là 5), tức là tại dấu nhắc lệnh ta phải viết tong(10,5); và sau khi
thực hiện chu trình trả lại kết quả là 15
Tham biến có tính cục bộ : chúng chỉ được sử dụng bên trong chu trình đã được khai báo, bên ngoài chu trình này chúng không mang ý nghĩa gì
Kiểu của tham biến có thể được khai báo trực tiếp
Trang 14Biến toàn cục
Biến toàn cục được khai báo sau từ khoá global trong khai báo chu trình
Biến toàn cục được khai báo bên trong một chu trình, nhưng có phạm vi giá trị trong toàn bộ chương trình, tức là bên ngoài phạm vi của chu trình mà nó được khai báo trong đó
Phân tích ví dụ sau, trong đó chu trình f chứa biến toàn cục x được gán giá trị là
10, chu trình g thực hiện việc in ra màn hình giá trị của biến x Rõ ràng biến x không được khai báo trong chu trình g nhưng vì nó được khai báo là toàn cục (global) trong chu trình f nên g có thể tác động lên x (in giá trị của nó) bên ngoài phạm vi chu trình f:
10
Biến cục bộ
Biến cục bộ được khai báo sau từ khoá local trong khai báo chu trình
Biến cục bộ chỉ có giá trị bên trong chu trình mà nó được khai báo Ngoài chu trình này nó không mang ý nghĩa gì
Ví dụ về chu trình f trong đó biến cục bộ a chỉ có giá trị trong chu trình, nhưng
không có giá trị sau khi chu trình kết thúc (tức là nó không còn hiệu lực với các lệnh nằm ngoài chu trình):
[>f:=proc()local a;global b;a:=10;b:=a+5;end;
[>f();
15[>b;
Trang 1515[>a;
a
Tham biến
Cũng giống như biến cục bộ, các tham biến chỉ có giá trị bên trong phạm vi của chu
trình mà nó được khai báo Sau khi chu trình kết thúc, chúng không còn giá trị
Tham biến còn được sử dụng để trả lại kết quả, như các ngôn ngữ lập trình truyền
thống Ngoài ra, do Maple có những hàm có khả năng trả lại nhiều hơn một giá trị
Ta có thể gộp các giá trị này vào một danh sách để trả lại như một phần tử
Sau đây ta lập lại chu trình kiểm tra xem một phần tử x có thuộc một danh sách L
hay không, nhưng ta đưa thêm một biến nữa trả lại kết quả cho biết vị trí của x trong danh sách L Trong ví dụ này ta sử dụng một tên riêng của Maple là nargs
(chỉ biến số lượng các biến trong chu trình) Nếu có tham biến chỉ vị trí thì ta có
Định giá tên hàm và tham biến
Như đã đề cập trước đây, các tên biến trong một biểu thức được Maple định giá trước khi thực hiện các phép tính trên chúng Đối với việc thực hiện các hàm cũng tương tự như vậy Trước tiên là tên chu trình được định giá Sau đó lần lượt đến các
đối số trong danh sách các đối số truyền cho chu trình (được định giá từ trái sang phải) Nếu tên chu trình được định giá trỏ đến một chu trình, thì chu trình ấy được
Trang 16thực thi trên các đối số đã đ−ợc định giá Tuy nhiên vẫn có một số chu trình ngoại
lệ: đó là các hàm eval, assigned, seq
Định giá biến cục bộ và biến toàn cục
Các biến cục bộ và tham biến truyền cho chu trình đ−ợc định giá một cấp (định giá một lần), còn các biến toàn cục thì đ−ợc định giá hoàn toàn (full evaluation) Hàm eval() đ−ợc dùng để ép định giá hoàn toàn cho biến cục bộ và tham biến, và
định giá một mức cho các biến toàn cục
[>restart; #khoi dong lai chuong trinh de xoa cac bien toan
cuc da khai bao o phan truoc
[>f:=proc()local p;global x;x:=2; p:=x^2+3*x-1; p; end;
Trang 17Vì Maple chỉ định giá biến cục bộ p đúng 1 lần (định giá thành biểu thức:
9
Tham biến p cũng chỉ được định giá đúng một lần (trước khi định giá x)
Ta có thể dùng hàm eval để thay đổi mức định giá:
[>restart;
[>g:=proc(p)global x;x:=2;eval(p);end;
[>g(x^2+3*x-1);
9
Các ngôn ngữ lập trình truyền thống cho phép gọi các hàm đệ quy, tức là các
hàm trong quá trình thực hiện có gọi đến chính nó Ví dụ sau trình bày một hàm đệ quy tính số Fibonacci được định nghĩa:
F = F = F =Fư +Fư
[>F:=proc(n)
if n=0 then 0 elif n=1 then 1 else F(n-1)+F(n-2) fi;
end;
Với chu trình này, ta có thể tính được các thành phần trong dãy Fibonacci, sau đây
là 15 số đầu tiên :
[>seq(F(i),i=1 15);
Trang 18, , , , , , , , , , , , , ,
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
Tuy nhiên, đây không phải là cách hiệu quả để tính các số Fibonacci Thủ tục này chỉ có thể tính với các số Fibonacci đầu tiên trong dãy, còn với những số Fibonacci lớn hơn thì không thể tính toán được Lí do là vì với mỗi F(i), Maple lại tính toán lại các giá trị F(i-1), F(i-2), , F(1), F(0) Với n càng lớn thì số các phép tính tăng lên
rất nhanh, ta có thể kiểm tra điều này bằng cách dùng biến printlevel để kiểm tra:
Chạy từng bước chu trình
Muốn in ra màn hình các "vòng lệnh ẩn" ta sử dụng biến printlevel Thí dụ
muốn cho máy có thể in ra các vòng lệnh đủ sâu ta gán cho biến này giá trị:
Trang 19Để giải quyết khó khăn này, Maple sử dụng một bảng gọi là bảng nhớ để lưu
các giá trị mà hàm vừa tính được Các chỉ mục của bảng là đối số của hàm còn các phần tử của bảng là các giá trị hàm tính được với chỉ mục tương ứng Mỗi khi hàm F(n) được gọi, trước hết Maple kiểm tra giá trị F(n) đã có trong bảng chưa, nếu đã
có thì hàm kết quả được lưu trong bảng nhớ, nếu chưa có thì nó thực hiện các lệnh
có trong hàm F với tham số n sau đó tự động lưu cặp n/F(n) vào trong bảng Để yêu cầu Maple sử dụng bảng nhớ, ta sử dụng tuỳ chọn remember ngay đầu chu trình Sau đây là ví dụ sử dụng tuỳ chọn này:
[>restart;
Trang 20[>F:=proc(n) options remember;
if n=0 then 0 elif n=1 then 1
Trang 22< exit F (now in F) = 135301852344706746049} value remembered (in F): F(97) ->
83621143489848422977
218922995834555169026
< exit F (now in F) = 218922995834555169026} value remembered (in F): F(98) ->
4.2.7 Sử dụng các hàm RETURN, ERROR
Hàm RETURN được sử dụng để cho giá trị hàm trước khi thoát khỏi chu trình Nếu không có lệnh RETURN, chu trình tự động cho kết quả của phép tính cuối cùng trong chu trình
Hàm ERROR được sử dụng để đưa thông điệp lỗi ra màn hình từ bên trong chu trình
Minh hoạ
Thiết lập chu trình tìm ước số chung lớn nhất (USCLN) của 2 số nguyên Chu trình sẽ cho ra thông báo lỗi nếu như số đưa vào không nguyên, và cho ra câu trả lời nếu cả 2 số đưa vào là nguyên
Trang 23Error, (in USCLN) co so khong nguyen
4.2.8 Một số ví dụ về chu trình
1 Chu trình tìm các thành phần tối đại trong một mảng
Vấn đề: Bài toán này là sự mở rộng của bài toán tìm số lớn nhất trong một tập
hợp số mà ta đã xét trong các ví dụ trước Các thành phần của một mảng không nhất thiết là những số, mà có thể gồm những biểu thức, nên vấn đề có phần phức tạp hơn Có những biểu thức so sánh được (thí dụ ta luôn cóx< + ), nhưng có x 1những biểu thức không thể so sánh được (khi ta chưa gán hết các giá trị số cho các biến) Những thành phần (trong mảng) mà không có thành phần nào khác (trong
mảng) lớn hơn nó thì được gọi là các thành phần tối đại Rõ ràng tập hợp của các
thành phần tối đại trong mảng chỉ gồm những thành phần hoặc là bằng nhau hoặc là không so sánh được với nhau Chu trình được thiết lập là để tìm tập hợp này Trong trường hợp riêng với mảng số ta được chu trình tìm tất cả (chứ không chỉ một) phần
tử lớn nhất trong một mảng số
ý tưởng chính của thuật toán là sử dụng hàm dấu (signum) để so sánh 2 thành phần Nếu 2 thành phần so sánh được với nhau (dấu của hiệu giữa chúng bằng +1 hoặc -1) thì ta loại đi cái nhỏ hơn Nếu một thành phần nào đó mà không so sánh
được với tất cả các thành phần còn lại của mảng thì cũng được giữ lại
Mô tả thuật toán: Lấy thành phần đầu tiên, so sánh với các thành phần còn lại; nếu phát hiện được một thành phần khác bé hơn nó thì ta huỷ thành phần bé bằng cách gán a[n] vào vị trí của nó (mảng còn lại bớt đi một phần tử); nếu thấy một thành phần khác lớn hơn nó thì ta cho thành phần này thế chỗ của nó rồi lại để cho a[n] thế vào chỗ của thành phần lớn hơn này (như vậy mảng còn lại cũng bớt đi 1 thành phần); nếu trong mảng chỉ có thành phần bằng hoặc không so sánh được với thành phần đã rút ra thì ta để nguyên nó đấy và xét mảng còn lại (cũng ít hơn mảng
cũ 1 thành phần) Tóm lại, sau mỗi vòng lặp thì mảng cần phải xét có số thành phần giảm đi 1, và trong trường hợp có thể thì nhặt ra được 1 thành phần không nhỏ hơn các thành phần nào trong mảng còn lại (và có thể bằng hoặc không so sánh được với các thành phần đã được nhặt ra ở các bước trước )
Chu trình được thiết lập như sau:
[>restart;
[>toidai:=proc() local a,i,j,n,s; #khai bao chu trinh va cac
bien cuc bo n:=nargs; #khai bao n la so cac bien (number of
arguments) a:=array(1 n); #khai bao a la mot mang gom n
thanh phan for i to n do a[i]:=args[i] od; #khai bao moi
thanh phan cua mang la mot argument i:=1;
Trang 24while i<n do j:=i+1;
while j<=n do s:=signum(a[i]-a[j]);
if s=1 then a[j]:=a[n]; #loai bo thanh phan a[j] bang cach
gan gia tri a[n] de len n:=n-1;
elif s=-1 then a[i]:=a[j];
Trang 25:=
a toidai , ,(j i π)[>i:=10; j:=5;
2 Chu trình tính khai triển Fourier của hàm số
Trong Maple có gói công cụ rất mạnh về biến đổi tích phân, trong đó có biến
đổi tích phân Fourier, và hầu hết các từ khoá liên quan đến chữ Fourier đều tham chiếu đến phép biến đổi này Các tính toán liên quan đến chuỗi Fourier còn ít được
đề cập đến Chúng ta sẽ thiết lập chu trình để lấp lỗ hổng này Ta biết rằng chuỗi Fourier của hàm ( )f x được tính theo công thức sau:
0 1
end:
Ngoài ra, ta lưu ý rằng với hàm lẻ và hàm chẵn thì các hệ số a b được tính n, nrất dễ dàng (không cần tính qua tích phân) Cho nên, để giảm bớt khối lượng tính
toán đối với các hàm kiểu này, ta đưa vào trong chu trình thêm một biến tc chỉ tính
chất chẵn-lẻ của hàm số (nếu có) Khi không có biến này (tức là hàm không có tính chẵn hoặc lẻ) thì các hệ số được tính theo công thức thông thường đã nói trên Nếu
ta không biết chắc hàm là chẵn hay lẻ thì không nên đưa vào biến thứ 3 (vì nếu khai báo sai thì chu trình sẽ tính sai, còn nếu không khai báo thì chương trình luôn tính
đúng mặc dù sẽ lâu hơn) Chu trình được thiết lập như sau
Chu trình tính hệ số a : n
[>a:=proc(n,f,tc)
local t;
Trang 26if nargs>2 then #neu co bien thu 3 thi tinh nhu
fi
else
lprint(`Loi`);
fi
tinh binh thuong
if n=0 then 1/Pi*int(f(t),t=-Pi Pi) else
Pi Pi))) fi
0
Chú ý Giá trị của tham biến f phải là một hàm (hình thức) chứ không phải là một
biểu thức, cho nên ta không thể viết sin(x) vào chỗ của hàm sin trong câu lệnh
trên Muốn biểu thị hàm đ−ợc sinh bởi biểu thức thì phải định nghĩa hàm bằng toán
tử mũi tên -> nh− ta đã biết
Thí dụ
[>a(n,x->x^2*sin(x),le);
0
Trang 27[>a(5,x->x^2);
-425[>a(5,x->x^2,chan);
-425
else lprint(`Loi`);
fi else map(combine,rutgon(1/Pi*int(sin(n*t)*f(t),t=- Pi Pi))) fi
0[>b(n,x->x^2+x^4,chan);
0[>b(n,x->x^3);
2( )-1 (n 1 + )π2n2 + 6 ( )-1 n
n3
Trang 28Chu trình tính khai triển Fourier của hàm số
[>Fourier:=proc(function,parameter)
local f,x,tc,un;
if nargs>2 then tc:=args[3]; #neu so bien lon hon
3 thi bien thu 3 la tc else # neu khong thi bien tc la khong co tc:=NULL
fi;
x:=parameter;
f:=function;
un:=a(n,f,tc)*cos(n*x)+b(n,f,tc)*sin(n*x); a(0,f,tc)/2+sum(un,n=1 infinity);
4.3 Tìm lỗi trong chu trình
4.3.1 Printlevel (Lần theo các bước của chu trình)
Mô tả
Cách đơn giản nhất để xem xét các quá trình thực hiện lệnh là sử dụng biến
printlevel Biến toàn cục printlevel điều khiển lượng thông tin được hiện ra màn
hình trong suốt quá trình thực hiện lệnh Thông tin được in ra màn hình bao gồm các phép gán, các biểu thức, các điểm vào và ra của chu trình Các mức độ của biến
printlevel:
Khi printlevel được gán giá trị âm thì không hiện gì cả (chỉ trừ tác dụng của các
lệnh print, lprint, printf, )
Khi printlevel được gán giá trị là 0 thì chỉ có kết quả của các câu lệnh là được hiện
ra
Với giá trị mặc định, chỉ có kết quả của các câu lệnh trong Maple, các câu lệnh bên
trong vòng lặp for/while và bên trong lệnh if thì được hiện ra màn hình Với giá
trị là 2 thì các lệnh lồng nhau 2 cấp được in ra màn hình
Với giá trị là 5 thì chu trình đầu tiên (không lồng trong chu trình khác) được in ra
Trang 29mµn h×nh C¸c c©u lÖnh lång trong vßng lÆp for/while hay bªn trong lÖnh if cña
chu tr×nh th× ®−îc in ra víi gi¸ trÞ b»ng 6 §Ó hiÖn ra mµn h×nh chu tr×nh lång trong mét chu tr×nh th× ta ph¶i dïng gi¸ trÞ 5*2=10 cho biÕn printlevel T−¬ng tù nh− thÕ
víi gi¸ trÞ 5*n th× hµm lång nhau cÊp n ®−îc in ra
{ > enter type/RootOf, args = 1 n
< exit type/RootOf (now in sum) = false}
ans 13(n 1 + )3 − 1 + +
2(n 1 + )2 1
6n
16
< exit sum (now at top level) =