Toán tử Python: số học, // và %, so sánh, and/or/not, round trong Python
Toán tử / trong Python luôn cho kết quả kiểu float, // lấy phần nguyên làm tròn xuống, % cho phần dư, ** là lũy thừa. Hàm round(x, n) làm tròn đến n chữ số thập phân theo kiểu «làm tròn đến số chẵn»: round(2.5) bằng 2, còn round(3.5) bằng 4; làm tròn lên và xuống đến số nguyên dùng math.ceil và math.floor, còn trị tuyệt đối của số là abs.
Toán tử trong Python là các ký hiệu biến giá trị thành giá trị mới: + cộng, // chia lấy nguyên, and kết hợp các điều kiện. Dưới đây là danh sách đầy đủ các toán tử kèm ví dụ, sự khác nhau giữa / và //, logic của and, or, not, và các hàm làm tròn: python round, math.ceil, math.floor và abs. Mọi ví dụ đều có thể dán vào REPL để kiểm tra.
Danh sách toán tử Python
Các toán tử được chia thành nhóm theo mục đích. Không cần nhớ cả bảng: trong code thực tế, bạn gặp nhiều nhất là số học, so sánh và các phép kết hợp logic.
| Nhóm | Toán tử | Ví dụ |
|---|---|---|
| Số học | + - * / // % ** | 7 // 2 → 3 |
| So sánh | == != < > <= >= | 3 < 5 → True |
| Logic | and or not | not True → False |
| Đồng nhất | is, is not | x is None |
| Thành viên | in, not in | "cà" in "cà phê" → True |
| Gán | = += -= *= /= //= %= **= | total += 250 |
| Walrus | := | if (n := len(s)) > 10: |
| Bitwise | & | ^ ~ << >> | 5 & 3 → 1 |
Toán tử số học
Phép cộng, trừ và nhân hoạt động như trên lớp học. Nếu trong biểu thức có ít nhất một float, kết quả cũng sẽ là float: 2 + 1.0 cho 3.0. Số nguyên trong Python không bị tràn — 2 ** 100 được tính chính xác, bất kể có bao nhiêu chữ số.
>>> 250 + 120
370
>>> 12.5 * 3
37.5
>>> 2 ** 10
1024
>>> 2 ** 0.5
1.4142135623730951
Lũy thừa trong Python: toán tử **
Lũy thừa được viết bằng hai dấu sao, không phải ^: dấu ^ trong Python là phép XOR theo bit, và 2 ^ 3 cho kết quả 1, không phải 8. Lũy thừa với số mũ thập phân cho căn: 9 ** 0.5 bằng 3.0. Còn có hàm pow(x, y) — làm việc tương tự, cộng thêm đối số thứ ba để lấy phần dư: pow(2, 10, 1000) trả về 24.
Lưu ý thứ tự ưu tiên: ** được thực hiện trước dấu trừ đơn, nên -2 ** 2 bằng -4. Nếu bạn cần bình phương một số âm, hãy viết ngoặc: (-2) ** 2.
Phép chia trong Python: /, // và %
Trong Python có hai kiểu chia, và đây là nguồn bất ngờ lớn nhất với người mới. Phép chia thông thường / luôn trả về float, kể cả khi chia hết. Phép chia nguyên // bỏ phần thập phân, còn % trả về phần dư.
>>> 7 / 2
3.5
>>> 8 / 2
4.0
>>> 7 // 2
3
>>> 7 % 2
1
Chia nguyên // và phần dư %: thực hành
Cặp // và % giải các bài toán kiểu «có bao nhiêu phần nguyên và còn dư bao nhiêu». Trong khóa học, trình theo dõi chi tiêu lưu tiền theo đơn vị xu để không mất độ chính xác, và tách tổng tiền thành đồng và xu:
cents = 125050 # lưu tiền theo đơn vị xu
dong = cents // 100 # 1250 — số đồng nguyên
xu = cents % 100 # 50 — phần dư
print(dong, xu) # 1250 50
print(40 // 7, "tuần và", 40 % 7, "ngày") # 5 tuần và 5 ngày
Cả hai phép được trả về cùng lúc bởi hàm tích hợp divmod: divmod(125050, 100) cho bộ (1250, 50). Phần dư cũng tiện để kiểm tra chẵn lẻ: n % 2 == 0 đúng với các số chẵn.
Số âm: // làm tròn xuống
Toán tử // không chỉ bỏ phần thập phân, mà làm tròn xuống, về phía âm vô cực. Với số dương thì không khác gì, còn với số âm thì có khác. Dấu của phần dư % trong Python trùng với dấu của số chia, nên luôn đúng đẳng thức a == (a // b) * b + a % b.
>>> -7 // 2
-4
>>> -7 % 2
1
>>> int(-7 / 2) # bỏ phần thập phân, không làm tròn xuống
-3
Chia cho 0: lỗi nào xảy ra
Chia cho 0 bằng bất kỳ toán tử nào trong ba toán tử trên đều gây ra ngoại lệ ZeroDivisionError. Điều này đúng cho cả số nguyên và số thập phân. Có thể bắt lỗi bằng try/except hoặc kiểm tra số chia trước.
>>> 10 / 0
Traceback (most recent call last):
...
ZeroDivisionError: division by zero
>>> count = 0
>>> avg = 1500 / count if count else 0
>>> avg
0
Toán tử so sánh
Các phép so sánh trả về True hoặc False. Phép bằng được kiểm tra bằng hai dấu ==, còn dấu = đơn là phép gán. Chuỗi được so sánh theo từng ký tự theo mã ký tự, nên "B" < "a" là đúng: chữ hoa đứng trước chữ thường.
>>> 250 == 250.0
True
>>> 3 != 4
True
>>> 1 < 5 <= 10 # chuỗi so sánh: 1 < 5 and 5 <= 10
True
>>> 0.1 + 0.2 == 0.3
False
Chuỗi so sánh như 0 <= x < 100 là một đặc điểm tiện lợi của Python: không cần viết and. Còn dòng cuối nhắc về sai số của số thập phân: 0.1 + 0.2 cho 0.30000000000000004. Khi so sánh số thực hãy dùng math.isclose(a, b), còn tiền hãy lưu theo đơn vị xu hoặc trong Decimal.
Toán tử logic and, or, not
Toán tử logic trong Python được viết bằng từ, không phải bằng ký hiệu && và || như trong các ngôn ngữ khác. and đúng khi cả hai vế đều đúng, or — khi ít nhất một vế đúng, not đảo giá trị.
| a | b | a and b | a or b | not a |
|---|---|---|---|---|
| True | True | True | True | False |
| True | False | False | True | False |
| False | True | False | True | True |
| False | False | False | False | True |
Thứ tự ưu tiên: trước hết là not, sau đó and, rồi đến or. Biểu thức True or False and False cho True, vì and được tính trước. Trong các điều kiện phức tạp hãy dùng dấu ngoặc — như vậy dễ đọc hơn cho bạn và đồng nghiệp.
Thực ra and và or trả về gì
and và or không nhất thiết trả về True hoặc False, mà trả về một trong các toán hạng. or cho giá trị đúng đầu tiên (hoặc giá trị cuối nếu không có giá trị đúng nào), and — giá trị sai đầu tiên (hoặc giá trị cuối). Các giá trị sai gồm 0, 0.0, chuỗi rỗng, các tập hợp rỗng, None và False.
>>> name = ""
>>> name or "Khách"
'Khách'
>>> 5 and 0
0
>>> not ""
True
Việc tính toán diễn ra lười: nếu kết quả đã rõ từ vế trái, vế phải không được tính. Vì vậy count and total / count không gây lỗi chia cho 0 khi count == 0. Toán tử not, khác với hai toán tử kia, luôn trả về bool.
Toán tử is và in
== so sánh giá trị, còn is kiểm tra xem hai tên có cùng trỏ đến một đối tượng hay không. Hai giỏ hàng rỗng khác nhau là bằng nhau, nhưng đó không phải là cùng một đối tượng. Chỗ duy nhất mà is được dùng thường xuyên là kiểm tra None: if x is None.
>>> a = [250, 120]
>>> b = [250, 120]
>>> a == b, a is b
(True, False)
>>> c = a
>>> c is a
True
Đừng so sánh số và chuỗi bằng is: đôi khi nó «chạy được» nhờ cơ chế cache nội bộ của đối tượng, nhưng kết quả phụ thuộc vào triển khai, và Python đưa ra SyntaxWarning với các cấu trúc như x is 5.
Toán tử in kiểm tra sự có mặt: chuỗi con trong chuỗi, phần tử trong danh sách, khóa trong từ điển. not in là kiểm tra ngược lại.
>>> "cà phê" in "cà phê sữa"
True
>>> "ăn uống" in {"ăn uống": 450, "taxi": 300}
True
>>> 5 not in [1, 2, 3]
True
Toán tử gán và toán tử walrus :=
Các toán tử gán ghép như +=, -=, *=, //= và các toán tử khác là cách viết tắt: total += 250 có nghĩa là total = total + 250. Python không có toán tử ++ và --: viết x++ sẽ gây lỗi cú pháp.
Toán tử walrus := (được đặt tên theo hình dáng giống mắt và ngà của con hải mã) gán giá trị ngay trong biểu thức. Nó hữu ích khi giá trị cần được vừa kiểm tra vừa dùng tiếp:
items = ["cà phê", "taxi", "cơm trưa", "phim"]
if (n := len(items)) > 3:
print(f"Quá nhiều khoản chi: {n}")
while (line := input("Số tiền: ")) != "":
print(int(line) * 2)
Nếu không có walrus, phải gọi len hai lần hoặc tách phép gán thành dòng riêng. Không nên lạm dụng: nếu dòng code trở nên khó đọc, phép gán thông thường sẽ tốt hơn.
Làm tròn trong Python: round, ceil, floor
Để làm tròn trong Python có hàm tích hợp round và các hàm của module math. Chúng giải quyết các bài toán khác nhau, và nhầm lẫn giữa chúng là lỗi phổ biến.
| Hàm | Làm gì | 2.5 | -2.5 | 2.7 |
|---|---|---|---|---|
round(x) | đến số gần nhất, nếu đúng giữa thì về số chẵn | 2 | -2 | 3 |
math.floor(x) | xuống, về phía âm vô cực | 2 | -3 | 2 |
math.ceil(x) | lên, về phía dương vô cực | 3 | -2 | 3 |
math.trunc(x), int(x) | bỏ phần thập phân, về phía 0 | 2 | -2 | 2 |
Hàm round trong Python và làm tròn kiểu ngân hàng
Hàm round(x, n) làm tròn đến n chữ số sau dấu phẩy; nếu không có đối số thứ hai, nó trả về int. Bẫy chính: python round làm tròn theo kiểu «ngân hàng» — khi đứng giữa thì về số chẵn gần nhất. Vì vậy round(2.5) cho 2, còn round(3.5) cho 4. Nhờ vậy sai số làm tròn không tích lũy theo một chiều khi tính toán lớn.
>>> round(2.5), round(3.5)
(2, 4)
>>> round(3.14159, 2)
3.14
>>> round(1250, -2) # đến hàng trăm
1200
>>> round(2.675, 2) # không phải 2.68: ở dạng nhị phân là 2.67499...
2.67
Nếu cần cách làm tròn «nửa lên» quen thuộc, ví dụ trên hóa đơn, hãy dùng Decimal với chế độ ROUND_HALF_UP. Truyền số dưới dạng chuỗi để không thừa hưởng sai số của float:
>>> from decimal import Decimal, ROUND_HALF_UP
>>> Decimal("2.5").quantize(Decimal("1"), ROUND_HALF_UP)
Decimal('3')
>>> Decimal("2.675").quantize(Decimal("0.01"), ROUND_HALF_UP)
Decimal('2.68')
Và một quy tắc khác từ khóa học: chỉ làm tròn khi hiển thị. Để in đẹp không cần round — đủ dùng f-string: f"{amount:.2f}" hiển thị hai chữ số thập phân, còn bản thân số vẫn chính xác.
math.ceil và math.floor: làm tròn lên và xuống
math.ceil cần khi «thiếu» là không được phép: cần thuê bao nhiêu xe buýt, bao nhiêu trang trong kết quả tìm kiếm. math.floor — khi chỉ tính các đơn vị đầy đủ. Cả hai hàm đều trả về int.
import math
guests = 47
seats = 20
print(math.ceil(guests / seats)) # 3 xe buýt
print(math.floor(9.99)) # 9
print(-(-guests // seats)) # 3 — ceil không cần math, dùng //
Module math còn có các hàm hữu ích khác: math.sqrt (căn bậc hai), math.isclose (so sánh số thực), math.pi, math.gcd. Trong Python 3.15 xuất hiện module con math.integer (PEP 791) cho toán học số nguyên: có comb, factorial, gcd, isqrt, lcm, perm, còn math.gcd cũ và các hàm khác vẫn hoạt động.
Hàm abs: trị tuyệt đối của số
abs(x) trả về trị tuyệt đối — khoảng cách từ 0 không kể dấu. Không cần import, hàm này được tích hợp sẵn. Hoạt động với số nguyên, số thực và thậm chí số phức: với 3+4j nó trả về độ dài vector, tức 5.0.
>>> abs(-250)
250
>>> abs(-12.5)
12.5
>>> budget, spent = 5000, 5320
>>> abs(budget - spent) # lệch bao nhiêu
320
Ứng dụng điển hình là hiệu không kể chiều và so sánh với sai số cho phép: abs(a - b) < 0.001. Với số thực đáng tin cậy hơn là math.isclose, vì nó tính đến độ lớn của các số.
Thứ tự ưu tiên của toán tử
Khi có nhiều toán tử trong một biểu thức, Python thực hiện chúng theo độ ưu tiên — từ cao xuống thấp:
**- toán tử một ngôi
-x,+x,~x * / // %+ -- dịch bit và các phép bit
- so sánh,
in,is notandor:=
Ví dụ, 2 + 3 * 4 bằng 14, còn (2 + 3) * 4 — bằng 20. Khi không chắc, hãy thêm dấu ngoặc: dấu ngoặc thừa không tốn gì, còn lỗi ưu tiên thì tìm rất lâu.
Lỗi thường gặp với toán tử
| Lỗi | Điều gì xảy ra | Cách đúng |
|---|---|---|
if x = 5: | SyntaxError: đây là phép gán | if x == 5: |
2 ^ 3 thay cho lũy thừa | XOR theo bit, kết quả 1 | 2 ** 3 |
mong chờ số nguyên từ 8 / 2 | nhận được 4.0 | 8 // 2 |
x == 1 or 2 | luôn đúng: or 2 | x in (1, 2) |
mong chờ 3 từ round(2.5) | làm tròn kiểu ngân hàng cho 2 | Decimal với ROUND_HALF_UP |
"5" + 5 | TypeError | int("5") + 5 |
Kết luận
Hãy nhớ điều chính: / luôn cho float, // làm tròn xuống, % trả về phần dư mang dấu của số chia, còn lũy thừa là **. Các toán tử logic and, or, not được viết bằng từ và tính toán lười, is dùng để kiểm tra None. Hàm python round làm tròn về số chẵn; để làm tròn lên và xuống có math.ceil và math.floor, trị tuyệt đối cho bởi abs. Trong khóa học các toán tử này được thực hành trên trình theo dõi chi tiêu, nơi tiền được lưu theo đơn vị xu.
Câu hỏi thường gặp
Làm sao làm tròn một số đến hai chữ số thập phân trong Python?
Dùng round(x, 2), còn nếu chỉ cần hiển thị đẹp thì dùng f-string f"{x:.2f}", vì nó không thay đổi giá trị của số.
Vì sao round(0.5) trong Python cho 0?
Vì round làm tròn số đứng giữa về số chẵn gần nhất, và 0 là số chẵn; tương tự round(1.5) và round(2.5) đều cho 2.
Làm sao lấy phần nguyên của phép chia trong Python?
Bằng toán tử //: 17 // 5 cho 3. Với số âm nó làm tròn xuống, nên -17 // 5 cho -4; nếu muốn bỏ phần thập phân về phía 0, hãy dùng int(-17 / 5).
Python có toán tử ba ngôi không?
Có, đó là biểu thức điều kiện: giá_trị_nếu_đúng if điều_kiện else giá_trị_nếu_sai, ví dụ "chẵn" if n % 2 == 0 else "lẻ".
& và and trong Python khác nhau thế nào?
and là toán tử logic có tính toán lười, còn & là AND theo bit cho số và giao cho tập hợp; trong điều kiện if hãy dùng and.
Chủ đề này được giảng chi tiết kèm thực hành trong khóa học “Python 3.15: от новичка до профи”.
Đến khóa học