Ký pháp nghịch đảo Ba-Lan và phương pháp tính giá trị biểu thức toán học
Khi lập trình, tính giá trị một biểu thức toán học là điều quá đỗi bình thường. Tuy
nhiên, trong nhiều ứng dụng (như chương trình vẽ đồ thị hàm số chẳng hạn, trong
đó chương trình cho phép người dùng nhập vào hàm số), ta cần phải tính giá trị của
một biểu thức được nhập vào từ bàn phím dưới dạng một chuỗi. Với các biểu thức
toán học đơn giản (như a+b) thì bạn có thể tự làm bằng các phương pháp tách
chuỗi “thủ công”. Nhưng để “giải quyết” các biểu thức có dấu ngoặc, ví dụ như
(a+b)*c + (d+e)*f, thì các phương pháp tách chuỗi đơn giản đều không khả thi.
Trong tình huống này, ta phải dùng đến Ký Pháp Nghịch Đảo Ba Lan (Reserve
Polish Notation – RPN), một thuật toán “kinh điển” trong lĩnh vực trình biên dịch.
Để đơn giản cho việc minh họa, ta giả định rằng chuỗi biểu thức mà ta nhận được
từ bàn phím chỉ bao gồm: các dấu mở ngoặc/đóng ngoặc; 4 toán tử cộng, trừ, nhân
và chia (+, -, *, /); các toán hạng đều chỉ là các con số nguyên từ 0 đến 9; không có
bất kỳ khoảng trắng nào giữa các ký tự.
Thế nào là ký pháp nghịch đảo Ba Lan?
Cách trình bày biểu thức theo cách thông thường tuy tự nhiên với con người nhưng
lại khá “khó chịu” đối với máy tính vì nó không thể hiện một cách tường minh quá
trình tính toán để đưa ra giá trị của biểu thức. Để đơn giản hóa quá trình tính toán
này, ta phải biến đổi lại biểu thức thông thường về dạng hậu tố - postfix (cách gọi
ngắn của thuật ngữ ký pháp nghịch đảo Ba Lan). Để phân biệt hai dạng biểu diễn
biểu thức, ta gọi cách biểu diễn biểu thức theo cách thông thường là trung tố –
infix (vì toán tử nằm ở giữa hai toán hạng).
Ký pháp nghịch đảo Ba Lan được phát minh vào khoảng giữa thập kỷ 1950 bởi
Charles Hamblin – một triết học gia và khoa học gia máy tính người Úc – dựa theo
công trình về ký pháp Ba Lan của nhà Toán học người Ba Lan Jan Łukasiewicz.
Hamblin trình bày nghiên cứu của mình tại một hội nghị khoa học vào tháng 6 năm
1957 và chính thức công bố vào năm 1962.
Từ cái tên hậu tố các bạn cũng đoán ra phần nào là theo cách biểu diễn này, các
toán tử sẽ được đặt sau các toán hạng. Cụ thể là biểu thức trung tố: 4+5 sẽ được
biểu diễn lại thành 4 5 +.
Quá trình tính toán giá trị của biểu thức hậu tố khá tự nhiên đối với máy tính. Ý
2
Push 2
5, 1, 2
+
Tính 1 + 2
Push 3
5, 3
4
Push 4
5, 3, 4
*
Tính 3 * 4
Push 12
5, 12
+
Tính 12 + 5
+ Chừng nào còn có một toán tử o
2
ở đỉnh ngăn xếp Và độ ưu tiên của
o
1
nhỏ hơn hay bằng độ ưu tiên của o
2
thì lấy o
2
ra khỏi ngăn xếp và ghi vào
kết quả.
+ Push o
1
vào ngăn xếp
Nếu gặp dấu đóng ngoặc thì cứ lấy các toán tử trong ngăn xếp ra và ghi vào
kết quả cho đến khi lấy được dấu mở ngoặc ra khỏi ngăn xếp.
Khi đã duyệt hết biểu thức trung tố, lần lượt lấy tất cả toán tử (nếu có) từ
ngăn xếp ra và ghi vào chuỗi kết quả.
Để dễ hiểu, bạn hãy quan sát quá trình thực thi của thuật toán qua một ví dụ cụ thể
sau:
Biểu thức cần chuyển đổi: 3+4*2/(1-5)
Ký
tự
Thao tác
Stack
Chu
ỗi hậu tố
2
Ghi 2 vào kqu
ả3 4 2
/
L
ấy * ra khỏi stack,
ghi vào k.quả, Push /
+ / 3 4 2 *
(
Push (
+ / (
3 4 2 *
1
Ghi 1 vào k.qu
ả
+ / (
3 4 2 * 1
Ghi 2 ra k.qu
ả
+ /
3 4 2 * 1
5
–
2Pop t
ất cả các toán tử
ra khỏi ngăn xếp và
ghi vào kết quả
3 4 2 * 1 5 – 2 / +
Dĩ nhiên là thuật toán được trình bày ở đây là khá đơn giản và chưa ứng dụng được
trong trường hợp biểu thức có các hàm như sin, cos,… hoặc có các biến. Tuy
nhiên, việc mở rộng thuật toán là hoàn toàn nằm trong khả năng của bạn nếu bạn
đã hiểu cặn kẽ thuật toán cơ bản này.