Kiểu dữ liệu số trong Python

Khi viết mã nguồn cho bất kỳ phần mềm nào, việc thao tác với các con số xảy ra rất thường xuyên. Do đó, các kiểu dữ liệu về số là một phần không thể thiếu của bất kỳ ngôn ngữ nào, và Python cũng không phải là ngoại lệ. Trong bài viết này, chúng ta sẽ cùng tìm hiểu về các kiểu dữ liệu về số (numbers) trong Python thông qua các ví dụ đơn giản.

Python hỗ trợ 3 loại kiểu dữ liệu số: số nguyên (integer – int), số thực (float) và số phức (complex). Tuy nhiên, số phức thường ít được sử dụng nên chúng ta sẽ tìm hiểu nhiều hơn về số nguyên và số thực trong bài viết này. Số phức sẽ được tìm hiểu kỹ hơn trong một bài viết khác.

Tham gia cộng đồng học tập Bumbii trên Discord

  • Chia sẻ, hỏi đáp, bàn luận các vấn đề học tập.
  • Gặp gỡ các anh chị, thầy cô có nhiều năm kinh nghiệm.
  • Cập nhật các kiến thức, tài liệu mới nhất.

Tham gia ngay!

1. Số nguyên (integer – int)

Số nguyên là tập hợp các số không có chứa phần thập phân, bao gồm cả các số nhỏ hơn 0 (số âm), số 0 và các số lớn hơn 0 (số dương). Ví dụ: -10, -5, 0, 100, 111… Để khai báo (tạo) một số nguyên trong Python, chúng ta chỉ việc đơn giản gán số nguyên đó cho một biến (variable) như ví dụ sau:

# Declare a "literal" number
num = 2024

(Trong cách gán giá trị trực tiếp như trên, số 2024 được gọi là “integer literal” vì giá trị được gõ trực tiếp vào trong code.)

Một cách khác để tạo ra số nguyên là ép kiểu (casting) từ một chuỗi (string) hợp lệ, cách này thường sẽ được dùng khi chương trình nhận vào giá trị được nhập bởi người dùng. Trong ví dụ dưới đây, chúng ta sẽ chuyển chuỗi “2024” thành số nguyên 2024:

num = int("2024")
print(num) # 2024

Để kiểm tra một biến thuộc kiểu dữ liệu nào, ta có thể sử dụng hàm type(). Mở rộng ví dụ trên, chúng ta sẽ kiểm tra xem kiểu dữ liệu của biến num có thật sự là số nguyên không:

# Cast string to integer
num = int("2024")
print(num) # 2024
print(type(num)) # <class 'int'>

Trong thực tế, khi làm việc với các số nguyên lớn, chúng ta thường gom nhóm các con số thành các nhóm có ba số, đồng thời phân chia các nhóm này bởi dấu phẩy hoặc chấm. Cách gom nhóm này giúp chúng ta dễ đọc các con số hơn, ví dụ: 1,000,000. Tuy nhiên Python không cho phép chúng ta dùng dấu phẩy hoặc chấm, mà cho phép chúng ta sử dụng ký tự gạch dưới (underscore) để làm điều này:

# Large number with underscores
large_num = 1_000_000
print(large_num) # 1000000

Một điều khá thú vị là số nguyên trong Python không có giới hạn về độ lớn, nghĩa là bạn có thể khai báo một con số rất lớn mà không phải lo lắng về việc tràn bộ nhớ (out of memory). Chúng ta sẽ tìm hiểu sâu hơn vì sao Python có thể làm được điều này trong các chủ đề nâng cao.

# There is no limit to how large an integer can be 

very_large_num = 123456789987654321123456789987654321123456789987654321123456789987654321
print(very_large_num) # 123456789987654321123456789987654321123456789987654321123456789987654321

2. Số thực (float)

Số thực là tập hợp các chữ số có chứa phần thập phân, ví dụ: 1.0, 3.14,… Python sử dụng kiểu dữ liệu float để lưu trữ và làm việc với các số thực:

# float datatype in Python
print(type(3.14)) # <class 'float'>

Tương tự như số nguyên, chúng ta tạo ra số thực bằng cách gán giá trị của số thực đó vào một biến hoặc ép kiểu (cast) từ một chuỗi ký tự. Ngoài ra, đối với các số thực dài, chúng ta cũng có thể dùng ký tự underscore để dễ đọc hơn:

# Declare a float number
float_num = 3.14
print(type(float_num)) # <class 'float'>

float_num_from_str = float("3.14")
print(float_num_from_str) # 3.14

large_float_num = 1_234_567_8910.123
print(large_float_num) # 12345678910.123

Ngoài các cách trên, chúng ta còn có thể sử dụng ký hiệu e (e notation) để biểu diễn số float, cấu trúc như sau:

AeB = A x 10^B

Ví dụ:
1e6 (A = 1, B = 6), 1e6 = 1 x 10^6 = 1000000.0
2e15 (A = 2, B = 15), 2e15 = 2 x 10^15 = 2000000000000000.0
1e-4 (A = 1, B =. 4), 1e-4 = 1 x 10^(-4) = 0.0001
# e notation
print(1e6) # 1000000.0
print(2e15) # 2000000000000000.0
print(1e-4) # 0.0001

Như có đề cập ở trên, số nguyên không có giới hạn về mặt độ lớn, nhưng Python lại có giới hạn về độ lớn của số thực. Để tìm được số float lớn nhất, ta dùng đoạn code sau:

# float max value
import sys
print(sys.float_info.max) # 1.7976931348623157e+308

Vậy điều gì xảy ra nếu chúng ta khai báo một số float lớn hơn số max ở trên? Số đó sẽ trở thành inf (infinity):

# infinity float number
inf_num = 2e308
print(inf_num) #inf
print(type(inf_num)) # <class 'float'>

Tham gia cộng đồng học tập Bumbii trên Discord

  • Chia sẻ, hỏi đáp, bàn luận các vấn đề học tập.
  • Gặp gỡ các anh chị, thầy cô có nhiều năm kinh nghiệm.
  • Cập nhật các kiến thức, tài liệu mới nhất.

Tham gia ngay!

3. Các phép toán trên số nguyên và số thực

3.1 – Các phép toán cộng, trừ, nhân, chia

Trong Python, các phép toán cơ bản như cộng (+), trừ (-), nhân (*), chia (/) cũng không có gì quá đặc biệt, tương tự như các phép toán các bạn thường gặp khi học Toán. Chỉ có phép nhân và chia thì bạn dùng các ký tự hơi khác biệt, do ký tự x (nhân) và : (chia) được Python hiểu theo một cách khác.

# Arithmethic operators 
print(1 + 2) # 3 
print(4 - 2) # 2

print(4.0 - 2) # 2.0
print(1.0 + 2.0) # 3.0
print(1.0 + 2) # 3.0 

print(3 * 4) # 12
print(3.0 * 4) # 12.0

print(18 / 3) # 6.0 

Một số lưu ý khi thực hiện các phép toán trên kiểu dữ liệu số trong Python:

  • Cộng, trừ hoặc nhân hai số nguyên sẽ cho ra kết quả là số nguyên. Nhưng nếu một trong hai toán hạng là số thực sẽ cho ra kết quả là một số thực.
  • Phép chia hai số luôn luôn cho ra kết quả là một số thực (kể cả khi hai toán hạng là số nguyên).
print(18 / 3) # 6.0
  • Cũng tương tự như trong Toán học, chúng ta không thể chia cho số 0. Nếu bạn làm điều này, bạn sẽ nhận được lỗi ZeroDivisionError
# Devide by 0
print(10 / 0)

# Lỗi: ZeroDivisionError: division by zero

3.2 – Phép chia lấy phần nguyên (integer division hay floor division)

Trong Python, chúng ta có thể dùng toán tử // để thực hiện phép chia có kết quả được làm tròn thành số nguyên. Chú ý: khi thực hiện phép toán này, Python sẽ làm tròn “xuống” (floor division), nên khi kết quả phép chia là số âm (nhỏ hơn 0) thì kết quả có thể không như bạn dự đoán.

# Integer division or floor division
print(10 // 2) # 5
print(5.0 // 2) # 2.0
print(-5 // 2) # -3

Trong ví dụ trên ta thấy 5.0 / 2 = 2.5 sẽ được làm tròn xuống 2.0, và -5 / 2 = -2.5 được làm tròn xuống -3 (chứ không phải -2)

3.3 – Phép toán lũy thừa (exponent)

Để thực hiện phép toán lũy thừa trong Python, ta dùng toán tử ** (2 dấu sao). Nếu cả hai toán hạng là số nguyên, kết quả sẽ là số nguyên, nếu ít nhất một trong hai số hạng là số thực thì kết quả sẽ là số thực.

# Exponent
print(3 ** 2) # 9
print(2 ** 3) # 8
print(9 ** 0.5) # 3.0 -> số thực vì 0.5 là số thực

Chúng ta cũng có thể thực hiện phép lũy thừa với số mũ là số nguyên âm (nhỏ hơn 0), dưới đây là công thức toán học tương ứng:

# a là số nguyên, b là số nguyên dương -> -b là số nguyên âm
Công thức: a ** -b = 1 / (a ** b)
print(2 ** -1) # = 1 / (2 ** 1) = 1 / 2 = 0.5
print(2 ** -2) # = 1 / (2 ** 2) = 1 / 4 = 0.25
print((-2) ** -2) # = 1 / ((-2) ** 2) = 1 / 4 = 0.25

3.4 – Phép chia lấy phần dư (modulus)

Trong Python, để thực hiện phép chia lấy phần dư chúng ta dùng toán tử %

# Modulus 
print(7 % 2) # 1
print(7 % 4) # 3
print(10 % 5) # 0

Theo kinh nghiệm cá nhân thì phép modulus này thường không được dùng nhiều như các phép toán khác. Một trong những ứng dụng của phép toán modulus là xác định một số là số chẵn (n % 2 == 0) hoặc số lẻ (n % 2 == 1).

Tham gia cộng đồng học tập Bumbii trên Discord

  • Chia sẻ, hỏi đáp, bàn luận các vấn đề học tập.
  • Gặp gỡ các anh chị, thầy cô có nhiều năm kinh nghiệm.
  • Cập nhật các kiến thức, tài liệu mới nhất.

Tham gia ngay!

4. Biểu thức (expression)

Cũng giống như trong toán học, trong Python bạn có thể kết hợp các con số, các phép toán và dấu ngoặc để tạo nên các biểu thức toán phức tạp hơn. Và các nguyên tắc trong toán học cũng được áp dụng tương tự trong Python, như trong một phép toán thì sẽ ưu tiên tính trong ngoặc trước hoặc các phép nhân/chia sẽ được tính trước các phép cộng/trừ.

# Expressions
print(3 + 5*2) # = 3 + 10 = 13
print((3+5) * 2) # = 8 * 2 = 16

Trong đoạn code trên, nếu các bạn để ý kỹ, bạn sẽ thấy khoảng trắng (whitespace) ở hai bên các toán tử (ví dụ: + hoặc *) không phải lúc nào cũng giống nhau. Lý do là chúng ta đang viết code theo các quy tắc (coding conventions) được mô tả trong tài liệu PEP8 (https://pep8.org). Dưới đây là một đoạn trích dẫn về quy tắc này để các bạn tham khảo (Nguồn: https://pep8.org/#other-recommendations):

If operators with different priorities are used, consider adding whitespace around the operators with the lowest priority(ies). Use your own judgment; however, never use more than one space, and always have the same amount of whitespace on both sides of a binary operator.

Tạm dịch: Nếu các toán tử có độ ưu tiên khác nhau, hãy xem xét việc thêm khoảng trắng (whitespace) ở hai bên của các toán hạng có độ ưu tiên thấp hơn. Tuy nhiên không nên dùng nhiều hơn một khoảng trắng…

Bằng cách áp dụng quy tắc này vào đoạn code, chúng ta cũng có thể dễ dàng biết được thứ tự ưu tiên của các phép toán hơn khi đọc code. Tuy nhiên, nếu bạn không thoải mái với quy tắc này vì cảm thấy phải luôn thêm khoảng trắng để đồng nhất code của mình, bạn có thể dùng dấu ngoặc để làm cho code dễ đọc hơn. Ví dụ dưới đây là 2 cách viết khác nhau:

3 + 5*2 # PEP8

3 + (5 * 2) # Dùng dấu ngoặc

5. Các hàm (function) toán học trong Python

Python cung cấp cho chúng ta một số hàm để làm việc với các con số như abs(), pow(), round()

5.1 – Tìm giá trị tuyệt đối với hàm abs() – absolute

Giá trị tuyệt đối của một số dương là chính nó, còn để tính giá trị tuyệt đối của một số âm thì ta nhân số âm này với -1 (hoặc ngắn gọn hơn là bỏ dấu trừ của số âm này đi). Nghĩa là hàm abs() sẽ luôn luôn trả về một số dương và kiểu dữ liệu sẽ là int (số nguyên) hoặc float (số thực) tùy vào con số chúng ta đưa vào hàm này.

# abs() 
print(abs(100)) # 100
print(abs(-100)) # 100
print(abs(-10.0)) # 10.0

5.2 – Lũy thừa với hàm pow()

Ở mục 3.3 phía trên, chúng ta đã biết cách tính lũy thừa trong Python sử dụng toán tử **. Ngoài cách này, chúng ta còn có thể sử dụng hàm pow() để tính lũy thừa:

# Công thức 
pow(x, y) = x ** y # x^y
# pow()
print(pow(5, 2)) # 25
print(pow(5, 2) == 5**2) # True

Ngoài cách sử dụng như trên, hàm pow() còn có thể nhận vào đối số thứ 3, trong trường hợp này, Python sẽ tính lũy thừa trước, sau đó sẽ tiếp tục thực hiện phép tính modulus (phép chia lấy dư). Công thức như sau:

pow(x, y, z) = (x ** y) % z
pow(5, 2, 3) = (5 ** 2) % 3 = 25 % 3 = 1

5.3 – Làm tròn số với hàm round()

Hàm round() được dùng để làm tròn một số thành một số nguyên gần nhất.

# round()
print(round(1.4)) # 1
print(round(1.8)) # 2

Nếu dùng hàm round() để làm tròn các số kết thúc bằng .5, đôi khi chúng ta sẽ nhận được kết quả khác với chúng ta dự đoán:

print(round(4.5)) # 4 ... Oops!

print(round(5.5)) # 6

Trong ví dụ trên, 4.5 được làm tròn thành 4 thay vì 5, lý do là Python 3 làm tròn số theo nguyên tắc rounding ties to even. Chúng ta sẽ tìm hiểu kỹ hơn về chủ đề này trong một bài viết (nâng cao) khác.

Tham gia cộng đồng học tập Bumbii trên Discord

  • Chia sẻ, hỏi đáp, bàn luận các vấn đề học tập.
  • Gặp gỡ các anh chị, thầy cô có nhiều năm kinh nghiệm.
  • Cập nhật các kiến thức, tài liệu mới nhất.

Tham gia ngay!

6. Số phức

Python là một trong số ít các ngôn ngữ có hỗ trợ số phức. Ôn lại một chút: số phức là số bao gồm 2 phần: phần thực (real) và phần ảo (imaginary):

# Cấu trúc số phức trong Python
# a: phần thực, b: phần ảo, j đơn vị ảo
a + bj

# Ví dụ:
3 + 4j 
7 + 10j

Chú ý: Trong Python thì bạn bắt buộc phải dùng ký tự j để biểu diễn đơn vị ảo, không được dùng các ký tự khác, nếu không Python sẽ báo lỗi.

Để lấy được giá trị phần thực và phần ảo của một số phức, ta dùng .real (thực) và .imag (ảo).

# Complex number
n = 3 + 4j
print(n.real) # 3.0
print(n.imag) # 4.0

Tương tự như số nguyên và số thực, Python cho phép chúng ta thực hiện các phép toán trên số phức (trừ phép chia lấy số nguyên – //):

# Complex number 
a = 3 + 4j
b = 5 - 7j

print(a + b) # (8-3j)
print(a - b) # (-2+11j)
print(a * b) # (43-1j)
print(a ** b) # (1937712.013104487-699433.9242374102j)
print(a / b) # (-0.17567567567567569+0.5540540540540542j)
# print(a // b) # Error: Operator "//" not supported for types "complex" and "complex"

Tổng kết:

Trong bài viết này, chúng ta đã tìm hiểu về số trong Python, bao gồm số nguyên, số thực và số phức. Thông qua các ví dụ đơn giản, các bạn đã học được:

  • Cách tạo ra các loại số trong Python.
  • Cách thực hiện các phép toán trên các con số: cộng, trừ, nhân, chia, chia lấy phần nguyên, chia lấy phần dư, lũy thừa.
  • Một số hàm toán học được tạo sẵn bởi Python: abs() – lấy giá trị tuyệt đối, pow() – lũy thừa, round() – làm tròn số.
  • Một số trường hợp đặc biệt bạn cần chú ý khi làm việc với các số trong Python.

Chúc các bạn học tốt. Happy coding!

Các code ví dụ trong bài viết các bạn có thể xem trên Github.

Python cơ bản

Python cơ bản

Phần 1: Kiến thức tổng quan

Cú pháp (syntax)

Biến (variables)

Chuỗi ký tự (strings)

Số (numbers) trong Python

Boolean trong Python

Vòng lặp trong Python

Danh sách (list) trong Python

Bộ dữ liệu (tuple) trong Python