Tag Archives: học sinh

Mô hình hóa hiện tượng vật lý bằng MATLAB

Được viết dành cho người mới học, cuốn sách này giới thiệu lập trình MATLAB và mô phỏng các hệ thống vật lý. Cuốn sách mở đầu với các giá trị vô hướng và dần dần nâng lên véc-tơ và ma trận. Các chủ đề được trình bày bao gồm biến và giá trị, đoạn mã lệnh, vòng lặp, phương trình vi phân thường, véc-tơ và hàm. MATLAB được dùng trọn vẹn trong cuốn này để giải quyết nhiều bài tập cuối chương. (trích thông tin từ Amazon.com)

Tác giả

Allen B. Downey là Phó giáo sư ngành Khoa học máy tính tại Franklin W. Olin College of Engineering. Ông đã viết một số cuốn sách, bao gồm Computational Modeling and Complexity Science, How to Think Like a Computer Scientist (Cách tư duy như nhà khoa học máy tính), The Little Book of Semaphores, Physical Modeling in MATLAB, và Learning Perl the Hard Way.

Mục lục

Chương 1: Các biến và giá trị
Chương 2: Mã lệnh chương trình
Chương 3: Vòng lặp

Chương 4: Véc-tơ
Chương 5: Hàm
Chương 6: Tìm nghiệm
Chương 7: Hàm số của véc-tơ
Chương 8: Phương trình vi phân thường
Chương 9: Hệ các PVT
Chương 10: Các hệ bậc hai
Chương 11: Tối ưu hóa và nội suy
Chương 12: Bây giờ véc-tơ mới thật là véc-tơ

Tiếp tục đọc

Advertisements

123 phản hồi

Filed under Mô hình hóa

Chương 12: Bây giờ véc-tơ mới thật là véc-tơ

Trở về Mục lục cuốn sách

Véc-tơ là gì?

Từ “véc-tơ” có thể mang những nghĩa khác nhau đối với từng người. Trong MATLAB, véc-tơ là một ma trận chỉ có một hàng, hoặc một cột. Cho đến giờ, ta đã dùng các véc-tơ của MATLAB để biểu diễn:

dãy:
Dãy là một tập hợp các giá trị được nhận diện bởi các chỉ số nguyên; theo cách làm tự nhiên ta có thể lưu các phần tử của dãy như những phần tử của một véc-tơ trong MATLAB.

véc-tơ trạng thái:
Véc-tơ trạng thái là một tập hợp các giá trị để mô tả trạng thái của một hệ vật lý. Khi gọi ode45, bạn cho nó các điều kiện ban đầu dưới dạng một véc-tơ trạng thái. Sau đó, khi ode45 gọi hàm tốc độ mà bạn lập nên, nó sẽ trả kết quả là một véc-tơ trạng thái khác.

ánh xạ rời rạc:
Nếu có trong tay hai véc-tơ cùng độ dài, bạn có thể hình dung chúng như một phép ánh xạ từ những phần tử của một véc-tơ này sang các phần tử thuộc véc-tơ kia. Chẳng hạn, ở Mục {Chuột}, kết quả thu được từ ode45 là các véc-tơ, TY; chúng biểu diễn một phép ánh xạ từ các giá trị thời gian của T sang các giá trị số lượng chuột có trong Y.

Trong chương này ta sẽ xét đến một công dụng khác của véc-tơ trong MATLAB: để biểu diễn các véc-tơ không gian. Một véc-tơ không gian là một giá trị nhằm biểu diễn một đại lượng vật lý nhiều chiều, như vị trí, vận tốc, gia tốc, hoặc lực1. Tiếp tục đọc

8 phản hồi

Filed under Mô hình hóa, Sách

Chương 11: Tối ưu hóa và nội suy

Trở về Mục lục cuốn sách

Các sự kiện dùng trong hàm ODE

Thường thì khi gọi ode45, bạn đều phải chỉ ra các thời điểm bắt đầu và kết thúc. Nhưng trong nhiều trường hợp, bạn không biết trước lúc nào việc mô phỏng cần kết thúc. Thật may là MATLAB cung cấp một cơ chế xử lý vấn đề này. Điều không hay là cơ chế này hơi lủng củng một chút. Sau đây là cách hoạt động:

  1. Trước khi gọi ode45 bạn dùng odeset để tạo ra một đối tượng có tên options để chứa các giá trị quy định cách hoạt động của ode45:
    options = odeset('Events', @events);
    

    Trong trường hợp này, tên của tùy chọn (option) là Events còn giá trị là một chuôi hàm. Khi ode45 hoạt động, nó sẽ gọi events sau mỗi bước thời gian. Bạn có thể gọi hàm này bằng bất cứ tên gọi nào, nhưng cái tên events thường được chọn theo thông lệ. Tiếp tục đọc

5 phản hồi

Filed under Mô hình hóa, Sách

Chương 10: Các hệ bậc hai

Trở về Mục lục cuốn sách

Hàm lồng ghép

Trong Mục ví dụ bài toán con vịt, ta đã thấy một ví dụ của tập tin M với hơn một hàm:

function res = duck()
    error = error_func(10)
end

function res = error_func(h)
    rho = 0.3;      % density in g / cm^3
    r = 10;         % radius in cm
    res = ...
end

Tiếp tục đọc

4 phản hồi

Filed under Mô hình hóa, Sách

Chương 7: Hàm số của véc-tơ

Trở về Mục lục cuốn sách

Hàm số và tập tin

Đến giờ ta mới chỉ đưa một hàm vào trong mỗi tập tin. Cũng có thể đặt nhiều hàm vào trong một tập tin, nhưng chỉ có hàm đầu tiên, hàm cấp cao nhất mới gọi được từ Command Window. Các hàm phụ trợ khác có thể được gọi từ bất kì đâu trong tập tin, nhưng không thể gọi từ tập tin khác.

Những chương trình lớn thường cần đến nhiều hàm; việc giữ tất cả các hàm trong cùng một tập tin tuy tiện lợi, nhưng làm cho việc gỡ lỗi trở nên khó khăn vì bạn không thể gọi các hàm phụ trợ từ Command Window.

Để giúp giải quyết vấn đề này, tôi thường dùng hàm cấp cao nhất để phat triển và thử nghiệm các hàm phụ trợ. Chẳng hạn, tôi có thể tạo ra một tập tin tên là duck.m và khởi đầu với một hàm cấp cao nhất có tên là duck mà không nhận vào bất kì biến đầu vào cũng như trả lại bất kì biến đầu ra nào. Tiếp tục đọc

4 phản hồi

Filed under MatLab, Mô hình hóa, Sách

Chương 6: Tìm nghiệm

Trở về Mục lục cuốn sách

Trong chương này ta sẽ thảo luận một chút về cách dùng hàm, qua đó lập mối quan hệ giữa toán và MATLAB. Tiếp theo là ứng dụng tìm nghiệm của một phương trình, một bài toán hay gặp trong thực tế.

Tại sao lại cần dùng hàm?

Chương vừa rồi đã giải thích một số ưu điểm của hàm, bao gồm

  • Mỗi hàm có không gian làm việc riêng của nó, vì vậy dùng hàm sẽ tránh được xung đột về tên.
  • Các hàm rất hợp với cách phát triển tăng dần: bạn có thể gỡ lỗi phần thân của hàm trước (dưới dạng tập tin lệnh), rồi gói nó vào trong một hàm, sau đó khái quát hóa bằng cách thêm các biến đầu vào.
  • Hàm cho phép ta chia một vấn đề lớn thành những phần nhỏ để xử lý từng phần một, rồi lắp ghép trở lại thành lời giải hoàn chỉnh.
  • Một khi đã có hàm chạy được, bạn có thể quên đi những chi tiết về cách hoạt động của nó, mà chỉ cần biết nó làm gì. Quá trình trừu tượng hóa này là một cách thức quan trọng để ta quản lý được sự phức tạp của những chương trình lớn.

Một lý do khác khiến bạn phải cân nhắc việc dùng hàm là nhiều công cụ quan trọng của MATLAB yêu cầu bạn phải viết hàm. Chẳng hạn, ở chương này ta sẽ dùng fzero để tìm nghiệm của phương trình phi tuyến. Sau đó ta sẽ dùng ode45 để tìm nghiệm xấp xỉ của các phương trình vi phân. Tiếp tục đọc

3 phản hồi

Filed under Mô hình hóa, Sách

Chương 5: Hàm

Trở về Mục lục cuốn sách

1. Sự xung đột về tên

Hãy nhớ rằng tất cả các tập tin lệnh bạn viết đều chạy trong cùng một không gian làm việc, vì vậy nếu một chương trình làm thay đổi giá trị một biến thì tất cả các chương trình khác đều thấy được sự thay đổi đó. Với một ít các chương trình đơn giản, điều này không đáng kể, nhưng rồi sau này những tương tác giữa các chương trình trở nên không thể quản lý được.

Chẳng hạn, chương trình sau tính tổng của n số đầu tiên trong một dãy hình học, nhưng cũng có hiệu ứng phụ là gán các giá trị cho A1, total, ia.

A1 = 1;
total = 0;
for i=1:10
    a = A1 * 0.5^(i-1);
    total = total + a;
end
ans = total

Tiếp tục đọc

5 phản hồi

Filed under Mô hình hóa, Sách

Chương 4. Véc-tơ

Trở về Mục lục cuốn sách

1. Kiểm tra điều kiện đầu

Một số vòng lặp ở chương trước sẽ không chạy đúng nếu giá trị của n không được đặt đúng trước khi vòng lặp bắt đầu chạy. Chẳng hạn, vòng lặp sau đây dùng để tính tổng của n phần tử đầu tiên của một dãy hình học:

A1 = 1;
total = 0;
for i=1:n
    a = A1 * 0.5^(i-1);
    total = total + a;
end
ans = total

Tiếp tục đọc

12 phản hồi

Filed under Mô hình hóa

Chương 3. Vòng lặp

Trở về Mục lục cuốn sách

1. Cập nhật các biến

Ở Bài tập cuối Chương 2, bạn có thể đã định viết

a = a - 0.05*a + 0.03*b
b = b + 0.05*a - 0.03*b

Nhưng điều đó sai, rất sai. Tại sao? Vấn đề là ở chỗ dòng lệnh thứ nhất thay đổi giá trị của a, nên khi dòng lệnh thứ hai được thực hiện, nó sẽ lấy giá trị cũ của b và giá trị mới của a. Kết quả là, sự thay đổi ở a không cùng lúc với thay đổi ở b; tức là đã vi phạm định luật bảo toàn số lượng xe! Tiếp tục đọc

4 phản hồi

Filed under MatLab, Mô hình hóa

Chương 2. Mã lệnh chương trình

Trở về Mục lục cuốn sách

1. Tập tin M

Đến giờ ta đã gõ tất cả chương trình “vào dấu nhắc lệnh”. Điều này cũng ổn nếu như bạn chỉ phải viết một vài dòng lệnh. Vượt quá mức đó, bạn sẽ cần lưu chương trình vào một tập tin lệnh rồi thực hiện tập tin lệnh này.

Một tập tin lệnh là một file (tập tin) chứa mã lệnh MATLAB. Các tập tin này cũng được gọi là “M-files” (tập tin M) vì chúng có phần mở rộng .m, vốn là chữ viết tắt cho MATLAB.

Bạn có thể tạo và sửa các tập tin lệnh với bất kì phần mềm biên tập file chữ (text editor) hay trình soạn thảo văn bản nào, nhưng cách làm dễ nhất là chọn New → Script từ trình đơn (menu) File. Một cửa sổ sẽ xuất hiện trong đó chạy một trình biên tập file chữ dành riêng cho MATLAB.

Hãy gõ dòng lệnh sau vào trong trình biên tập

x = 5 

và ấn vào biểu tượng đĩa mềm (giờ đã lỗi thời), hoặc chọn Save từ trình đơn File. Dù bằng cách nào đi nữa, một hộp thoại sẽ xuất hiện tại đó bạn có thể chọn tên tập tin và thư mục cần lưu vào. Hãy đổi tên thành myscript.m và giữ nguyên thư mục.

MATLAB, theo mặc định, sẽ lưu tập tin lệnh của bạn vào trong thư mục đặt ở đường dẫn được tìm kiếm (search path), vốn là một loạt các thư mục mà MATLAB tìm các tập tin lệnh ở đó.

Hãy quay trở lại Command Window và gõ vào myscript (không có phần mở rộng) tại dấu nhắc lệnh. MATLAB sẽ thực hiện tập tin lệnh và hiển thị kết quả.

>> myscript 
x = 5 

Khi bạn chạy một tập tin lệnh, MATLAB thực hiện các lệnh trong tập tin M, lần lượt từng lệnh một, hệt như khi bạn gõ chúng từ dấu nhắc.

Nếu có vấn đề trục trặc là MATLAB không thể tìm thấy tập tin lệnh thì bạn sẽ nhận được một thông báo lỗi kiểu như:

>> myscript 
??? Undefined function or variable 'myscript'. 

Trong trường hợp này bạn có thể lưu lại tập tin lệnh vào một thư mục có trong đường dẫn tìm kiếm, hoặc sửa lại đường dẫn tìm kiếm để nó bao gồm cả thư mục đang chứa tập tin lệnh này. Về chi tiết, bạn sẽ phải tra cứu tài liệu. (Rất xin lỗi!)

Tên tập tin có thể là bất cứ gì bạn thích, nhưng nên chọn những tên có nghĩa và dễ nhớ. Bạn phải rất cẩn thận chọn được một tên mà hiện không sử dụng; vì nếu tên đó mà đang được dùng thì bạn có thể sẽ vô tình thay thế nó vào các hàm có sẵn trong MATLAB. Sau cùng, tên tập tin không được phép có dấu cách. Nếu bạn tạo ra file có tên my script.m, MATLAB không phàn nàn gì cho đến khi bạn chạy nó:

>> my script 
??? Undefined function or method 'my' for input arguments of type 'char'. 

Vấn đề là ở chỗ nó đang cố tìm một tập tin lệnh có tên my. Sự việc còn tồi tệ hơn nữa nếu như từ đầu tiên của tên tập tin lại là một hàm sẵn có. Để cho vui, bạn hãy thử tạo một tập tin lệnh có tên abs val.m và chạy nó.

Việc theo dõi tất cả những tập tin lệnh của bạn có thể sẽ vất vả. Để cho mọi thứ trở nên đơn giản, tạm thời bây giờ bạn nên đặt tất cả tập tin lệnh vào trong thư mục mặc định.

Dãy Fibonacci, kí hiệu F, được mô tả bởi các phương trình F1=1, F2=1, và với i ≥ 3, Fi=Fi-1+Fi-2. Các số trong dãy này thường xuất hiện trong tự nhiên ở nhiều loại cây, đặc biệt là ở những cánh hoa hay vẩy được sắp xếp theo hình thù xoáy ốc.

Biểu thức sau được dùng để tính số Fibonacci thứ n:

Hãy chuyển biếu thức này sang MATLAB và lưu mã lệnh vào một tập tin có tên là fibonacci1. Tại dấu nhắc lệnh, hãy đặt n bằng 10 và chạy đoạn mã. Dòng cuối cùng của đoạn mã cần phải gán giá trị của Fn cho ans. (Giá trị đúng của F10 là 55).

2. Tại sao cần dùng tập tin lệnh?

Những lý do thông thường nhất cho việc dùng mã lệnh là:

  • Khi bạn đang viết nhiều câu lệnh (nhiều hơn một vài dòng), có thể bạn cần thử vài lần trước khi mã lệnh chạy đúng. Việc đặt mã vào trong một tập tin lệnh sẽ giúp bạn dễ chỉnh sửa hơn là gõ lệnh từ dấu nhắc.Mặt khác, bạn có thể thấy khó khăn khi phải chuyển đổi qua lại giữa Command Window và Editor (trình biên tập). Hãy thử sắp xếp các cửa sổ sao cho bạn có thể đồng thời thấy được cả Editor và Command Window, và dùng phím Tab hoặc chuột để chuyển giữa chúng.
  • Nếu bạn chọn tên hợp lý cho tập tin lệnh, bạn sẽ nhớ được là tập tin nào làm nhiệm vụ gì, và bạn có thể sẽ sử dụng lại được một tập tin lệnh của dự án này cho dự án sau.
  • Nếu bạn chạy tập tin lệnh nhiều lần, việc gõ tên tập tin lệnh sẽ nhanh hơn là gõ lại toàn bộ mã lệnh!

Không may là sức mạnh của các tập tin lệnh cũng đi kèm với trách nhiệm của người dùng; bạn phải chắc rằng mình chạy đúng tập tin lệnh mà mình cần.

Thứ nhất, mỗi khi chỉnh sửa tập tin lệnh, bạn phải lưu nó lại trước khi chạy. Nếu quên không lưu, bạn sẽ chạy phiên bản cũ của tập tin.

Thứ hai, mỗi khi bạn tạo một tập tin lệnh mới, hãy bắt đầu viết đơn giản, kiểu như x=5, để có được kết quả hiện ra rõ ràng. Sau đó chạy tập tin lệnh để chắc rằng bạn nhận được kết quả như mong đợi. MATLAB có rất nhiều hàm định nghĩa sẵn. Rất dễ viết một tập tin lệnh có tên giống như tên hàm của MATLAB, và nếu không cẩn thận, bạn có thể thấy rằng mình đã chạy hàm của MATLAB thay vì tập tin lệnh vừa viết.

Dù trong trường hợp nào, nếu mã lệnh mà bạn chạy không phải là mã lệnh bạn vừa sửa đổi thì bạn sẽ thấy việc gỡ rỗi thật phát bực! Và điều này dẫn ta đến Định lý thứ ba về gỡ lỗi:

Bạn phải chắc chắn 100% rằng mã lệnh bạn đang chạy đúng là mã lệnh bạn muốn chạy.

3. Không gian làm việc

Các biến bạn vừa tạo ra được lưu vào trong một không gian làm việc, hay “workspace”, vốn là một tập hợp các biến cùng giá trị của chúng. Lệnh who in ra các tên biến có trong không gian này.

>> x=5; 
>> y=7; 
>> z=9; 
>> who 
Your variables are: x y z 

Lệnh clear xóa bỏ hết các biến.

>> clear y 
>> who 
Your variables are: x z 

Để hiển thị giá trị một biến, bạn có thể dùng hàm disp.

>> disp(z) 
9 

Nhưng sẽ dễ hơn nếu ta chỉ gõ tên biến.

>> z 
z = 9 

(Chặt chẽ mà nói thì tên biến cũng chính là một biểu thức, vì vậy việc lượng giá nó sẽ gán giá trị cho ans, nhưng dường như MATLAB hiểu điều này như một trường hợp đặc biệt.)

4. Các lỗi khác

Một lần nữa, khi thử điều gì mới, bạn nên cố ý tạo ra một số lỗi để sau này còn nhận ra chúng.

Lỗi thông thường nhất với các tập tin lệnh là chạy một tập tin mà không tạo trước các biến cần thiết. Chẳng hạn, fibonacci1 yêu cầu bạn gán một giá trị cho n. Nếu bạn không gán:

>> fibonacci1 
??? Undefined function or variable "n". 

Error in ==> fibonacci1 at 4 
diff = t1^(n+1) - t2^(n+1); 

Chi tiết của thông báo lệnh này có thể sẽ khác trong trường hợp của bạn, tùy theo nội dung mã lệnh bạn gõ vào tập tin. Nhưng ý tưởng chung là n chưa được định nghĩa. Lưu ý rằng MATLAB báo với bạn dòng lệnh trong chương trình có lỗi xảy ra, và hiển thị dòng đó.

Thông tin này có thể hữu ích, nhưng hãy cẩn thận! MATLAB báo với bạn chỗ phát hiện ra trục trặc, chứ không phải là vị trí của lỗi. Ở trường hợp này, lỗi không hề nằm ở tập tin lệnh; mà đúng ra là ở không gian làm việc.

Từ đó dẫn đến Định lý thứ tư về gỡ lỗi:

Các thông báo lỗi báo cho ta biết trục trặc được phát hiện ở đâu, chứ không phải là nơi khởi nguồn của nó.

Mục đích của ta là tìm ra nguyên nhân và sửa nó—chứ không phải chỉ là làm cho thông báo lỗi biến đi.

5. Các điều kiện trước và sau

Mỗi tập tin lệnh đều nên chứa một lời chú thích nhằm trình bày tác dụng của nó, và những yêu cầu của nó đối với không gian làm việc. Chẳng hạn, tôi có thể gõ những dòng sau vào đầu tập tin fibonacci1:

% Computes the nth Fibonacci number. 
% Precondition: you must assign a value to n before running 
% this script. Postcondition: the result is stored in ans. 

Một điều kiện trước (“precondition”) là điều buộc phải đúng lúc chương trình bắt đầu được thực hiện, để chương trình có thể chạy đúng. Một điều kiện sau (“postcondition”) là điều sẽ đúng sau khi chương trình kết thúc.

Nếu có một lời chú thích như vậy ở đầu tập tin lệnh, MATLAB sẽ coi đó là đoạn thông tin của tập tin lệnh, vì vậy nếu bạn gõ vào help fibonacci1, bạn sẽ nhận được nội dung đoạn thông tin này (trừ những dấu phần trăm).

>> help fibonacci1 
Computes the nth Fibonacci number. 
Precondition: you must assign a value to n before running this script. 
Postcondition: the result is stored in ans. 

Bằng cách đó, các tập tin lệnh mà bạn viết ra sẽ thể hiện giống như các hàm đã định nghĩa sẵn. Thậm chí, bạn có thể dùng cả lệnh doc để xem đoạn thông tin từ Help Window.

6. Phép gán và đẳng thức

Trong toán học, dấu bằng dùng để chỉ hai vế của phương trình có cùng giá trị. Trong MATLAB một phép gán trông giống như một đẳng thức toán học, nhưng thực ra thì không phải.

Một điểm khác biệt là hai vế của một phép gán thì không thể đổi chỗ cho nhau được. Vế phải có thể được thay bởi một biểu thức hợp lệ bất kì, nhưng vế trái thì nhất thiết là một biến, được gọi là đích của phép gán. Vì vậy các lệnh gán sau đều hợp lệ:

>> y = 1; 
>> x = y+1 
x = 2 

Nhưng lệnh gán sau thì không:

>> y+1 = x 
??? y+1 = x 
        | Error: The expression to the left of the equals sign is not a valid target for an assignment. 

Trong trường hợp này thông báo lỗi khá là có ích, chỉ cần bạn hiểu được “đích” là gì.

Một điểm khác biệt nữa là ở chỗ phép gán chỉ là tạm thời, theo nghĩa sau đây. Khi bạn gán x = y+1, bạn nhận được giá trị hiện thời của y. Nếu sau này y thay đổi, x sẽ không thay đổi theo.

Điểm khác biệt thứ ba là một đẳng thức toán là một phát biểu có thể đúng hoặc không đúng. Chẳng hạn, y=y+1 là một phát biểu sai với mọi giá trị của y. Trong MATLAB, y = y+1 là câu lệnh gán hợp lệ và có ích. Nó đọc vào giá trị hiện thời của y, tăng thêm một, và thay thế giá trị cũ với giá trị mới này.

>> y = 1; 
>> y = y+1 
y = 2 

Khi đọc mã lệnh MATLAB, bạn có thể thấy sẽ lợi hơn khi đọc dấu bằng là “nhận giá trị” thay vì “bằng.” Do vậy x = y+1 được đọc là “x nhận giá trị của y cộng với 1.”

Để kiểm tra mức độ hiểu các lệnh gán của bạn, hãy thử làm bài tập sau:

Hãy viết một số dòng lệnh nhằm tráo đổi giá trị của hai biến Write a few lines of code that swap the values of xy. Đặt mã lệnh bạn viết vào trong tập tin có tên là swap và chạy thử nó.

7. Phát triển tăng dần

Khi bạn bắt đầu viết mã lệnh dài hơn một vài dòng, lúc đó bạn có thể thấy mình dành càng nhiều thời gian để gỡ lỗi. Nếu như bạn viết càng nhiều mã lệnh trước khi bắt tay vào việc gỡ lỗi thì bạn sẽ càng khó tìm ra trục trặc tiềm ẩn trong chương trình.

Phát triển tăng dần là một cách lập trình nhằm giảm thiểu công sức dành cho gỡ lỗi. Các bước cơ bản của nó gồm có:

  1. Luôn bắt đầu với một chương trình chạy được. Nếu bạn có một ví dụ trong sách hoặc một chương trình mà bạn đã viết tương đồng với chương trình đang làm, thì hãy lấy nó để bắt đầu. Còn nếu không, hãy bắt đầu với điều mà bạn biết rằng luôn đúng, như x=5. Chạy chương trình và khẳng định chắc rằng bạn đang chạy chương trình mà bạn muốn chạy.Bước này rất quan trọng, vì ở đa số các môi trường [xây dựng chương trình], có rất nhiều điều nhỏ nhặt làm bạn rối lên mỗi khi bắt đầu một dự án mới. Hãy dẹp chúng qua một bên để có thể tập trung vào lập trình.
  2. Mỗi lúc chỉ sửa một chỗ, và có thể kiểm tra được chỗ sửa này. “Kiểm tra được” có nghĩa ảnh hưởng của việc sửa đổi có thể hiện trên màn hình và bạn kiểm tra được. Tốt nhất là bạn cần biết được rằng kết quả đúng là gì, hoặc có khả năng kiểm tra nó bằng một phép tính toán khác.
  3. Chạy chương trình xem sự thay đổi có hiệu quả không. Nếu có, hãy quay trở lại Bước 2. Nếu không, bạn cần phải gỡ lỗi, nhưng nếu sự thay đổi nói trên rất nhỏ thì thường bạn sẽ nhanh chóng tìm ra lỗi.

Khi quá trình trên hoạt động tốt, bạn sẽ thấy rằng thường những thay đổi có tác dụng ngay lần đầu, hoặc sai lầm (nếu có) sẽ dễ thấy. Đó là một điều tốt, và dẫn đến Định lý thứ năm về gỡ lỗi:

Cách gỡ lỗi tốt nhất là cách mà ở đó bạn không phải làm.

Trên thực tế, có hai vấn đề gắn với phát triển tăng dần:

  • Đôi khi bạn phải viết thêm mã lệnh để có thể tạo ra kết quả dưới dạng nhìn thấy được, giúp cho việc kiểm tra. Mã lệnh thêm vào này được gọi là dàn giáo vì bạn dùng nó để xây dựng chương trình nhưng sau này sẽ bỏ nó đi khi chương trình hoàn tất. Nhưng thời gian tiết kiệm được từ việc gỡ lỗi thường luôn xứng đáng với thời gian bỏ ra để dựng dàn giáo.
  • Khi bạn mới bắt đầu, thông thường sẽ không rõ bằng cách nào bạn có thể chọn các bước kế tiếp từ x=5 đến chương trình mà bạn muốn viết. Có một ví dụ về cách làm này ở Mục [Ví dụ về phát triển tăng dần].

Nếu bạn tự thấy mình viết nhiều dòng lệnh trước khi bắt tay vào kiểm tra, và phải dành nhiều thời gian để gỡ lỗi thì bạn nên thử cách phát triển tăng dần.

8. Kiểm tra thành phần

Trong những dự án phần mềm lớn, kiểm tra thành phần là quá trình kiểm tra những bộ phận riêng biệt cấu thành phần mềm, trước khi sắp xếp chúng lại.

Những chương trình ta viết đến giờ đều chưa đủ lớn đến mức phải kiểm tra thành phần, nhưng chính nguyên tắc này cũng có ích khi lần đầu bạn thao tác với một hàm mới hoặc một đặc điểm mới của ngôn ngữ. Bạn cần kiểm tra nó riêng biệt trước khi đưa vào chương trình.

Chẳng hạn, giả sử rằng bạn biết là x là sin của một góc nào đó và bạn muốn tính góc này. Bạn tìm thấy hàm MATLAB có tên asin, và tương đối chắc rằng nó được dùng để tính nghịch đảo của sin. “Tương đối chắc chắn” vẫn là chưa đủ; bạn phải tuyệt đối chắc chắn.

Vì ta đã biết sin0 = 0, ta có thể thử

>> asin(0) 
ans = 0 

vốn là kết quả đúng. Hơn nữa, ta đã biết sin của góc 90 độ bằng 1, vì vậy nếu ta thử asin(1), ta muốn kết quả bằng 90, phải không?

>> asin(1) 
ans = 1.5708 

Ối! Chúng ta quên mất rằng các hàm lượng giác trong MATLAB đều tính theo ra-đian, chứ không phải độ. Vì vậy đáp số đúng là π/2, và ta có thể khẳng định bằng cách chia kết quả cho pi:

>> asin(1) / pi 
ans = 0.5000 

Với cách kiểm tra thành phần như thế này, bạn không thực sự kiểm tra lỗi trong MATLAB, mà kiểm tra cách hiểu của bạn. Nếu bạn mắc lỗi chỉ vì đã hiểu sai cách hoạt động của MATLAB thì sẽ mất rất nhiều thời gian để tìm ra lỗi đó; vì khi nhìn vào mã lệnh bạn tưởng như nó đúng.

Từ đó dẫn đến Định lý thứ sáu về gỡ lỗi:

Những lỗi tệ nhất không nằm ở mã lệnh mà ở trong đầu bạn.

9. Thuật ngữ

tập tin M:
Tập tin có chứa một chương trình MATLAB.
tập tin lệnh:
Tập tin M có chứa một loạt các lệnh MATLAB.
đường dẫn tìm kiếm:
Một loạt các thư mục tại đó MATALAB tìm các tập tin M.
không gian làm việc:
Tập hợp các biến cùng giá trị của chúng.
điều kiện đầu:
Điều mà buộc phải đúng khi chương trình bắt đầu chạy, để đảm bảo cho chương trình hoạt động đúng đắn.
điều kiện sau:
Điều sẽ đúng khi chương trình hoàn tất.
đích:
Biến ở vế trái của lệnh gán.
phát triển tăng dần:
Cách lập trình thông qua việc tạo ra một loạt những thay đổi nhỏ có thể kiểm tra được.
dàn giáo:
Mã lệnh được viết để phục vụ cho việc lập trình hoặc gỡ lỗi, nhưng không phải là một phần của sản phẩm chương trình.
kiểm tra thành phần:
Quá trình kiểm tra phần mềm bằng việc kiểm tra mỗi thành phần một cách riêng biệt.

10. Bài tập

Hãy tưởng tượng rằng bạn là chủ sở hữu một công ty cho thuê xe hơi với hai địa điểm, Albany and Boston. Một số khách hàng của bạn thuê “một chiều”, nghĩa là thuê xe lái từ Albany đến Boston, hoặc ngược lại. Sau một thời gian quan sát, bạn nhận thấy rằng mỗi tuần có 5% số xe đi từ Albany được trả ở Boston, và 3% số xe đi từ Boston được trả ở Albany. Vào đầu mỗi năm, có 150 xe ở mỗi trạm. Hãy viết một tập tin lệnh có tên car_update để cập nhật số xe ở mỗi trạm theo từng tuần. Điều kiện đầu là các biến ab chứa số xe ở mỗi địa điểm vào đầu hàng tuần. Điều kiện cuối là ab sau khi thay đổi, phản ánh số xe đã di chuyển.

Để kiểm tra chương trình, hãy đặt các giá trị đầu cho ab tại dấu nhắc lệnh và chạy tập tin lệnh. Chương trình cần hiển thị các giá trị được cập nhật của ab, nhưng không phải các biến trung gian khác.

Lưu ý rằng các xe là lượng đếm được, vì vậy ab phải luôn là những giá trị nguyên. Bạn có thể sẽ cần dùng hàm round để tính số xe di chuyển trong mỗi tuần.

Nếu thực hiện tập tin lệnh lặp đi lặp lại, bạn có thể mô phỏng sự di chuyển của xe từ tuần này qua tuần khác. Bạn nghĩ điều gì sẽ xảy ra với số xe? Liệu rằng tất cả các xe sẽ tụ về một trạm không? Liệu số xe sẽ đạt tới trạng thái cân bằng, hay dao động từ tuần này qua tuần khác?

Ở chương tiếp theo ta sẽ đề cập đến cách tự động thực hiện tập tin lệnh, này và cách vẽ đồ thị các giá trị của ab theo thời gian.

9 phản hồi

Filed under MatLab, Mô hình hóa