Tuesday, March 17, 2015

Ngôn Ngữ Lập Trình C



I. Giới thiệu ngôn ngữ lập trình C

1. Ngôn ngữ C là một ngôn ngữ lập trình tổng quát gọn gàng được phát triển bởi Dennis Ritchie cho hệ điều hành UNIX từ đầu thập niên 1970. Từ đó, ngôn ngữ này đã được sử dụng rộng rãi và hiệu quả trong nhiều hệ điều hành khác và trở thành một trong những ngôn ngữ phổ dụng nhất.
Các trình dịch, các thư viện và các phần mềm của các ngôn ngữ bậc cao khác thường được tạo nên từ C.
Năm 1989, ANSI C (American National Standards Institute) đã trở thành chuẩn cho ngôn ngữ lập trình C.

2. Thư viện chuẩn C
ANSI C định nghĩa một thư viện chuẩn gồm những hàm căn bản mà ta có thể dùng trong những chương trình C.
<ctype.h>: gồm các hàm xử lí các kiểu kí tự.
<float.h>: gồm các hằng theo kiểu số không nguyên, như số nhỏ nhất bởi _EPSILON, số lớn nhất bởi _DIG và khoảng cách của các số được biểu thị bởi _MIN và _MAX. 
<limits.h>: gồm các hằng theo kiểu số nguyên, như khoảng cách của các số được biểu thị bởi _MIN và _MAX. 
<math.h>: gồm các hàm toán thông dụng.
<setjmp.h>: gồm các hàm dùng tránh sự gọi (call) và trả lại (return) thông thường của hàm.
<signal.h>: gồm các hàm xử lí các điều kiện ngoại lệ.
<stdarg.h>: gồm các hàm truy cập các đối số được chuyển vào hàm.
<stdio.h>: gồm các hàm nhập xuất các kiểu dữ kiện, các định nghĩa macro.
<stdlib.h>: gồm các hàm chuyển đổi các kiểu số, cấp phát vùng nhớ, kiểm soát quá trình, tìm kiếm, và xếp thứ tự.
<string.h>: gồm các hàm xử lí các dãy kí tự. 

3. Cài đặt trình biên dịch C
Để hành xử một chương trình C, trước hết nó phải được biên dịch từ mã nguồn (chữ viết) thành mã máy (nhị phân) cho máy tính hiểu. Đây là công việc của trình biên dịch. Một trong những trình biên dịch C thông dụng nhất là trình GCC (GNU C Compiler). GCC hoàn toàn miễn phí bởi bằng công cộng tổng quát (General Public License).
Nếu GCC không có trong hệ điều hành Window, ta có thể tải xuống và cài đặt MinGW (Minimalist GNU) cho Window theo những bước sau:
2) Nhấn Download “Automated MinGW Installer”, giống như mingw-get-inst-xxx.exe
3) Nhấn hai lần Download “Automated MinGW Installer”, chấp nhận những điều khoản của bằng.
4) Chấp nhận nơi cài đặt ở C:\MinGW, nhấn Next để bắt đầu sự cài đặt.
5) Để xem trình biên dịch này đã cài đặt trong máy tính hay chưa, ta có thể viết lệnh sau đây ở cổng lệnh:
           C:\> gcc -v
rồi nhấn Enter để thấy
           C:\> gcc –v
           Using built-in specs.
           Thread model: win32
           Gcc version 4.6.1 (GCC)
Nghĩa là GCC đã được cài đặt.

4. Viết chương trình C
Những câu lệnh trong chương trình C muốn được hành xử phải đặt ở trong một hàm. Mỗi hàm được định nghĩa theo ngữ pháp sau đây:
           Loại dữ kiện Tên hàm () {những câu lệnh}
Sau khi hàm được gọi do hành xử câu lệnh, nó có thể trả lại cho vật gọi một giá trị thuộc loại dữ kiện ở trước tên hàm.
Một chương trình thường có một hoặc nhiều hàm, nhưng luôn luôn có một hàm tên “main” (chính). Hàm main() là điểm bắt đầu của tất cả các chương trình C. Trình biên dịch C sẽ không biên dịch mã của chương trình, nếu không tìm thấy chưong trình main().
Những hàm khác trong chương trình có thể có bất cứ tên nào dùng kí tự, số, và gạch dưới, nhưng không bắt đầu bằng số hạng và không có những kí tự riêng của C.
Ngoặc đơn () sau tên hàm có thể chứa những giá trị gọi là đối số của hàm, đuợc cách biệt bởi dấu phẩy.
Ngoặc móc {} chứa những câu lệnh được hành xử mỗi khi hàm được gọi. Mỗi câu lệnh phải được kết thúc bởi dấu chấm phẩy.
Thông thường, chương trình đầu tiên cho một ngôn ngữ lập trình là chương trình viết một câu chào, như  “Hello World.”,  theo những bước sau đây:
1) Mở trình viết chữ, như Notepad, viết mã ở đầu trang như  sau:
           #include <stdio.h>
Lệnh tiền xử lí này luôn đứng ở đầu chương trình để trình biên dịch dùng tập thư viện stdio.h trong chương trình này.
2) Hai hàng kế là hàm main rỗng
           Int main()
           {
           }
Hàm này khai báo kiểu dữ kiện nguyên sẽ được trả lại khi hàm được hành xử.
3) Giữa những ngoặc móc là một câu lệnh gọi một hàm trong thư viện stdio.h
           Printf( “Hello World!\n” );
Hàm printf() cần một dãy kí tự trong ngoặc đơn. Trong C, dãy kí tự này lại phải ở trong ngoặc kép. Dãy này gồm có Hello World và \n (hàng mới) dùng để chuyển đầu máy in xuống một hàng mới.
4) Giữa những ngoặc móc, ta thêm một câu lệnh để trả lại giá trị nguyên như hàm đã khai báo.
           Return 0;
Trả lại gía trị 0 nghĩa là chương trình đã hành xử đúng đắn.
5) Kiểm tra chương trình giống như sau đây:

           #include <stdio.h>

           int main(void)
           {
           printf(“Hello World!\n”);
           return 0;
           }
6) Lưu giữ chương trình này với tên “hello.c”

5. Biên dịch chương trình C
Tập nguồn hello.c được biên dịch thành tập hello.exe theo những bước sau:
1) Ở cổng lệnh, viết lệnh cd với đường dẫn tới hello.c
2) Ở cổng lệnh, nếu chỉ viết
           gcc hello.c
rồi nhấn Enter thì chương trình này được biên dịch thành a.exe; đây là chương trình chung cho tất cả các tập .c và sẽ bị xoá sau khi biên dịch một chương trình .c khác.
3) Để có được một tên riêng cho mỗi chương trình, ta phải viết rõ ở cổng lệnh
           gcc hello.c –o hello.exe
rồi nhấn Enter để biên dịch hello.c thành hello.exe
4) Ở cổng lệnh, viết
           C:\ Chương Trình\hello.exe
rồi nhấn Enter thì chương trình này sẽ cho kết quả mong đợi như  sau:
           Hello World!

6. Tìm hiểu sự biên dịch
Từ tập nguồn C đến tập hành xử (exe), sự biên dịch trải qua 4 giai đoạn. Mỗi giai đoạn làm ra một tập mới, như sau:
1) Bộ tiền xử lí thay thế các tập .h, như tập #include<stdio.h>, bằng các mã thư viện để sản xuất ra tập .i
2) Bộ biên dịch chuyển mã cao của tập .i thành mã thấp của tập .s
3) Bộ hợp ngữ chuyển mã thấp của tập .s thành mã máy (nhị phân) của tập .o
4) Bộ nối liên kết một hoặc nhiều tập .o thành mã hành xử (nhị phân) của tập .exe
Nếu tập nguồn .c có những thiếu sót trong ngữ pháp, bộ biên dịch sẽ báo cáo những sai lầm và sự biên dịch không có kết quả.
Nếu tập .o có những hàm cùng tên, bộ nối sẽ báo cáo những sai lầm và những tập .exe sẽ không được tạo thành.
Những tập tạm thời khi biên dịch thường bị xoá huỷ, nhưng muốn có những tập tạm ấy, thì khi biên dịch, ta phải để -save-temps trong lệnh biên dịch như sau:
Ở cổng lệnh, viết
           gcc hello.c –save-temps –o hello.exe
rồi nhấn Enter để biên dịch chương trình và lưu giữ các tập tạm thời.
Mở tập hello.i trong Notepad mã nguồn đã được thay thế bởi mã thư viện của tập stdio.h
Mở tập hello.s trong Notepad để thấy sự chuyển đổi thành mã thấp nhị phân của máy.


Monday, March 2, 2015

Hàm phức



I. Số phức

1. Dạng đại số của số phức

Số phức z là số có dạng đại số z = a + bi, với a và b là các số thực, i  đơn vị ảo, với i2 = -1.
Số thực a được gọi là phần thực của z, kí hiệu là Re(z).
Số thực b được gọi là phần ảo của z, kí hiệu là Im(z).
Và bi được gọi là số thuần ảo của z.
2. Mặt phẳng phức
Số phức z = a + bi có thể được biểu diễn trên mặt phẳng Đề-các, gọi là mặt 
phẳng phức hay mặt phẳng z, với trục hoành là trục thực và trục tung là trục ảo.
Như vậy, số phức z = a + bi xác định một điểm có toạ độ (a, b).
Hình 1.1
Biểu diễn số phức z và số phức liên hợp trong mặt phẳng phức.
Thí dụ:    
           Số phức −3.5 + 2i có:
           Re(-3.5 + 2i) = -3.5 là số thực.
           Im(-3.5 + 2i) = 2 là số ảo.
Như thế, số phức z được viết là
           z = Re(z) + Im(z)i. 

3. Số phức liên hợp

3.1 Định nghiã

Cho số phức z = a + bi khác 0, số phức  = a – bi được gọi là số phức liên hợp của z.

3.2 Tính chất của số phức liên hợp:
           1)   z x  =  a+ blà một số thực.       
   
           2) + '
              
           3)  x '

           4)    '

4. Đại số của số phức

Cho hai số phức khác 0, z = a + ib và w = m + in

4.1 Hai số phức bằng nhau
           z = w nếu và chỉ nếu a = m và b = n.
4.2 Phép cộng và trừ hai số phức:
           z + w = a + ib + m + in = (a + m) + i(b + n)
           z - w = a + ib – (m + in) = (a - m) + i(b - n)
4.3 Phép nhân hai số phức:
           zw = (a + ib)(m + in) = am + ian + ibm + i2bn
               = am + ian + ibm – bn
               = (am - bn) + i(an + bm)
4.4 Phép chia hai số phức:
 
Nếu dùng số liên hợp, ta có:
             
5. Tam giác Pascal

Để triển khai những số phức dạng (x + y)n, ta có thể dùng những hệ số của tam giác Pascal dưới đây

                                    1

                                  1  1

                               1   2   1

                             1   3   3   1

                          1   4   6   4   1

                                  . . .

Hàng thứ nhất là (x + y)0 = 1

Hàng thứ hai là (x + y)1 = (x + y)

Hàng thứ ba là (x + y)2 = x2 + 2xy + y2

Hàng thứ tư là (x + y)3 = x3 + 3x2y + 3xy2 + y3

Hàng thứ năm là (x + y)4 = x4 + 4x3y + 6x2y2 + 4xy3 + y4

Thí du:

           (2-i)4 = 2+ 4(23)(-i) + 6(22)(-i)2 + 4(2)(-i)3 + (-i)4

                    = 16 – 32i + 24(-i)2 + 8(-i)3 + (-i)4

                    = 16 – 32i -24 + 8i + 1

                    = -7 – 24i

6. Trường số phức

Tập hợp tất cả các số phức hay trường số phức được ký hiệu là C.

Cho u, w, z là 3 số phức Î C, thì những tiên đề sau:
6.1 Phép cộng:
           1) z + w Î C (tính đóng kín).
           2) z + w = w + z (tính giao hoán).
           3) (u + w) + z = u + (w + z)  (tính kết hợp).
           4) Đơn vị cộng 0 thoả mãn z + 0 = 0 + z = z.
           5) Nghịch đảo cộng, kí hiệu –z, thoả mãn z + (-z) = (-z) + z = 0.
6.2 Phép nhân:
           6) zw Î C (tính đóng kín).
           7) zw = wz (tính giao hoán).
           8) (uw)z = u(wz) (tính kết hợp).
           9) Đơn vị nhân 1 thoả mãn z.1 = 1.z = z.
           10) Nghịch đảo nhân, kí hiệu z-1, thoả mãn zz-1 = z-1z = 1.
6.3 Tính phân bố của cộng và nhân:
           11) (w + z)u  = wu + zu.
           12) u(w + z) = uw + uz.
Các tiên đề trên được thoả mãn và C được gọi là trường số phức.

7. Dạng cực của số phức


Hình 1.2

Toạ độ cực của số phức z.

7.1 Môđun
Cho số phức z = a + bi, thì z x = a+ b2.
Căn bậc hai của z x  được gọi là môđun của z, kí hiệu là |z|.
Như vậy, 
           |z| =                                  
Tính chất của môđun
           1) || = |z|
           2) |z1z2| = |z1||z2|
           3) |zn| = |z|n
           4) |z1/z2| = |z1|/|z2|                
           5) Bất đẳng thức tam giác
               | z1  + z2 |< |z1| + |z2|
               | z+ z2 + … + zn|< |z1| + |z2| + … + |zn|
               | z1  + z2 |> |z1| - |z2|
               | z1  - z2 |> |z1| - |z2|
7.2 Acgumen
Cho số phức z = a + bi, thì góc q giữa chiều dương của trục thực Ox và đường thẳng Ođược gọi là acgumen của z, kí hiệu là arg(z). 
Giá trị chính của arg(z), kí hiệu Arg(z), là giá trị duy nhất q mà -p < q £ p.
Ta có đẳng thức:
           arg(z) = Arg(z) + 2np,       n = 0, ±1, ±2, …
Giá trị chính cũng có thể là giữa 0 và 2p.
Tính chất của  acgumen
           1) arg(z1 x z2) = arg(z1) + arg(z2)
           2) arg(z1/z2) = arg(z1) - arg(z2)
           3) arg(zn) = n arg(z)
7.3 Định nghĩa

Số phức z = a + bi có thể viết dưới dạng

           z = a + bi =(a /  + ib /).

Đặt

           r = |z|, q = arg(z),
ta có:
           z = r(cosq + isinq)
gọi là dạng cực của z. 
Chú ý: Để biến đổi giữa số phức z dạng đại số và dạng cực, ta dùng
           r = |z| > 0 và tanq = b/a

7.4 Phép toán trên các số phức dạng cực

Cho hai số phức dạng cực khác 0,
           z = r(cosq + i sinq)
           z’ = r’(cosq’ + i sinq’)
1) Hai số phức dạng cực bằng nhau
nếu và chỉ nếu
           r = r’ và q = q    
2) Phép nhân số phức dạng cực
           z  z’ = r r’ (cos(q + q’) + i sin(q + q’))
3) Phép chia số phức dạng cực
           z/z' = r/r' (cos(q - q’) + i sin(q - q’))
4) Luỹ thừa số phức dạng cực (công thức Moivre).
           z= rn (cos(n q) + i sin(n q))
5) Khai căn số phức dạng cực
Mọi số phức khác 0 đều có đúng n căn bậc n, là các số dạng cực
           w=(cosyk + i sinyk)
           yq/n + (k2p)/n, với k = 0, 1, …, n – 1.
8. Dạng  của số phức
8.1 Định nghĩa
Dùng công thức Euler:
           eiq = cosq + i sinq
ta có thể viết số phức z = r(cosq + isinq) dưới dạng mũ
           z = reiq
8.2 Phép toán trên các số phức dạng 
Cho hai số phức dạng mũ khác không
           z1 = r1 eiq1 và z2 = r2 eiq2
1) Hai số phức dạng mũ bằng nhau
nếu và chỉ nếu
           r1 = r2 và q1 = q+ 2npΠ
2) Phép nhân dạng mũ
           eiq1 eiq= (cosq1 + isinq1) (cosq2 + isinq2)
                       = (cosq1 cosq2 - sinq1 sinq2) + i(sinqcosq2 + cosq1 sinq2)
                       = cos(q1 + q2) + isin(qq2)
                       = ei(q1 + q2)
Suy ra,
            z1 z2 = r1 r2 ei(q1 + iq2)
Như vậy, muốn nhân hai số phức, ta nhân môđun và cộng acgumen.
3) Phép chia dạng mũ
z1/z2  = r1/r2.(eiq1 e-iq2)/(eiq2 e-iq2)= r1/r2ei(q1 - q2)/ei0) = r1/r2ei(q1 - q2)
Như vậy, muốn chia hai số phức, ta chia môđun và trừ acgumen.
4) Luỹ thừa dạng mũ (Công thức De Moivre)
Với z1 = 1 = 1eio và z= z = reiq, ta có nghịch đảo của z:
           1/z = z-1 = 1/r e-iq
Ta cũng có số liên hợp của z:
           = r e-iq
Với z1 = z= z = reiq, ta có
           z2 = r2ei2q
Dùng quy nạp, ta có thể chứng minh rằng
           zn = reinq, n Î Z
Nếu r = 1, thì công thức trên trở thành
           (eiq)n = einqΠ
Đây là công thức De Moivre
           (cosq + i sinq)n =  cos(n q) + i sin(n q), Î 
5) Căn và luỹ thừa phân của số phức
Cho số phức z khác không.
a. Căn bậc n của z là bất cứ số phức w nào thoả mãn
           wn = z
Cho z = reiq  và w = reij , ta có
           rneinj  = reiq 
Suy ra,
             r = r 
Và         nj = q + 2kp, kÎZ
Nếu gọi là căn bậc n của số thực dương r, ta có
           r =
           jq/n + (k2p)/n kÎ
Do đó, các căn bậc n của z là các số phức
           wk = ei(q/n + (2kp)/n)kÎZ
Với dạng mũ này, tất cả căn bậc n của z đều nằm trên vòng tròn tâm O bán kính  
và cách đều nhau một góc 2p/n, bắt đầu từ góc q/n.
Vậy, ta chỉ có n căn khi k = 0, 1, 2, …, n-1, vì bất cứ số phức z = reiq khác không nào 
cũng chỉ có n căn bậc  n:     
           wk =ei(q/n + (2kp)/n), (k = 0, 1,2, …, n-1)
Thí dụ: Tìm căn bậc n của 1.
Xét phương trình
           z= 1, nÎZ+
Vì        (ez)= ezez…ez
Căn bậc n của 1 là
           cos2kp/n + isin2kp/n = e2kpi/n , k= 0, 1,2, …, n-1
Nếu     w = e2pi/n, thì căn bậc n là 1, w, w2, …, wn-1.
Thí dụ: Tìm căn bậc 4 của 2.
Để tìm căn bậc n của một số a, ta viết
           reinq = a ei0
Rồi cân bằng môđun và acgumen.
Lặp lại thủ tục này bởi cộng thêm 2p, ta có:
Căn thứ nhất là:
           (reiq)4 = 2 ei0
Suy ra,
           r = 21/4,      q = o
Căn thứ hai là:
           (reiq)4 = 2 ei2p
Suy ra,
           r = 21/4,      q = p/2
           z = 21/4 eip/2 = 21/4[cos(p/2) + isin(p/2)] = i21/4
Căn thứ ba là:
           (reiq)4 = 2 ei4p
Suy ra,
           r = 21/4,      q = p
           z = 21/4 eip = 21/4[cos(p) + isin(p)] = -21/4
Căn thứ bốn là:
           (reiq)4 = 2 ei6p
Suy ra,
           r = 21/4,      q = 3p/2
           z = 21/4 ei3p/2 = 21/4[cos(3p/2) + isin(3p/2)] = -i21/4
b. Luỹ thừa phân của một số phức z được định nghĩa như sau:

           zm/n = (z1/n)m = ()ei(q + 2kp), (k = 0, 1,2, …, n-1)