4.1 Làm tròn số thực
Số thực (số thập phân) trong tiếng Anh gọi là
float
ing point number — số có dấu phẩy động: ở Mỹ để phân chia phần nguyên và phần thập phân của số
thì dùng dấu chấm. Từ đó có tên gọi float
.
Như chúng ta đã nói, khi chuyển đổi số thực (float) thành số nguyên (int), nó luôn được làm tròn xuống đến số nguyên - phần thập phân của nó đơn giản là bị loại bỏ. Và bạn có thể dễ dàng tưởng tượng ra tình huống khi mà số thập phân cần được làm tròn đơn giản đến số nguyên gần nhất. Vậy làm gì trong tình huống này?
Để làm điều này trong Python có hàm tích hợp
round()
. Nó được tạo ra từ trước khi thư viện math, nên không thuộc vào thư viện này. Các hàm để làm tròn xuống và làm tròn lên
nằm trong thư viện math.
Hàm round()
làm tròn số đến số nguyên gần nhất:
round(so_thuc)
Hàm này sẽ trả về số nguyên gần nhất với số thực được truyền vào. Quan trọng là nếu phần thập phân của số bằng
0.5, hàm round()
sử dụng phương pháp làm tròn đến số nguyên chẵn gần nhất. Điều này được gọi là "làm tròn ngân hàng" và cho phép
giảm lỗi hệ thống khi làm tròn nhiều lần. Ví dụ:
Ví dụ:
Lệnh | Kết quả |
---|---|
x = round(4.1) | 4 |
x = round(4.5) | 4 |
x = round(4.9) | 5 |
x = round(5.5) | 6 |
Hàm math.ceil()
làm tròn số lên số nguyên, ví dụ:
Lệnh | Kết quả |
---|---|
x = math.ceil(4.1) | 5 |
x = math.ceil(4.5) | 5 |
x = math.ceil(4.9) | 5 |
Hàm math.floor()
làm tròn xuống, ví dụ:
Lệnh | Kết quả |
---|---|
x = math.floor(4.1) | 4 |
x = math.floor(4.5) | 4 |
x = math.floor(4.9) | 4 |
Dù để làm tròn số xuống số nguyên thì đơn giản hơn sử dụng hàm chuyển đổi kiểu int()
:
Lệnh | Kết quả |
---|---|
x = int(4.9) | 4 |
Nếu bạn cảm thấy khó khăn khi nhớ lệnh này, một bài học nhỏ về tiếng Anh sẽ giúp:
math
— toán họcround
— vòng/làm trònceiling
— trần nhàfloor
— sàn nhà
4.2 Cấu trúc số có dấu phẩy động
Kiểu float
trong Python có thể lưu trữ giá trị trong khoảng
-1.7*10308 đến +1.7*10308. Phạm vi giá trị khổng lồ như vậy được giải thích
bởi vì kiểu float
được cấu trúc hoàn toàn khác so với kiểu số nguyên.
Mỗi biến kiểu float chứa hai con số: con số đầu tiên được gọi là mantissa, và con số thứ hai là số mũ.
Giả sử, chúng ta có số 123456789, và chúng ta lưu nó vào
biến kiểu float
. Khi đó số sẽ được chuyển đổi thành dạng
1.23456789*108, và trong kiểu float
sẽ lưu trữ hai số -
23456789 và 8.
Màu đỏ là 'phần có ý nghĩa của số' (mantissa), màu xanh là số mũ.
Cách tiếp cận này cho phép lưu trữ cả số rất lớn và số rất nhỏ. Nhưng vì kích thước số giới hạn bởi 8 byte (64 bit) và một phần của bit được sử dụng để lưu trữ số mũ (cũng như dấu của số và dấu của số mũ), độ dài tối đa của mantissa được giới hạn ở 15 chữ số.
Đây là mô tả rất đơn giản hóa về cấu trúc của số thực, bạn có thể tìm kiếm thêm chi tiết hơn.
4.3 Mất độ chính xác khi làm việc với số thực
Khi làm việc với số thực, luôn cần nhớ rằng
số thực là không chính xác. Sẽ luôn có
lỗi làm tròn, lỗi chuyển đổi
từ
hệ thập phân sang hệ nhị phân và, cuối cùng và phổ biến nhất là -
mất độ chính xác
khi cộng/trừ số
có kích thước quá khác nhau.
Điều cuối cùng là tình huống rất bất ngờ cho những người mới bắt đầu lập trình.
Nếu từ số 109 trừ đi 1/109, chúng ta vẫn nhận được 109.
Trừ các số có kích thước quá khác nhau | Giải thích |
---|---|
|
Số thứ hai quá nhỏ, và phần có ý nghĩa của nó bị bỏ qua (đánh dấu màu xám). Màu vàng cam đánh dấu 15 chữ số có ý nghĩa. |
Phải nói gì nhỉ, lập trình không phải là toán học.
4.4 Nguy hiểm khi so sánh số thực
Một nguy hiểm khác rình rập các lập trình viên khi so sánh số thực. Vì khi làm việc với các số này có thể tích lũy các lỗi làm tròn, nên có thể tình huống xảy ra là khi mà các số thực cần bằng nhau, nhưng chúng lại không bằng nhau. Và ngược lại: các số cần khác nhau, nhưng chúng lại bằng nhau.
Ví dụ:
Lệnh | Giải thích |
---|---|
a = 1000000000.0 b = 0.000000001 c = a – b |
Trong biến a sẽ có giá trị 1000000000.0 Trong biến c sẽ có giá trị 1000000000.0 (số trong biến b quá nhỏ) |
Trong ví dụ trên, a và c không nên bằng nhau, nhưng chúng lại bằng nhau.
Hoặc hãy lấy một ví dụ khác:
Lệnh | Giải thích |
---|---|
a = 1.00000000000000001 b = 1.00000000000000002 |
Trong biến a sẽ có giá trị 1.0 Trong biến b sẽ có giá trị 1.0 |
Trong thực tế, số thực so sánh như sau:
Lấy một số rất nhỏ. Nếu sự khác biệt của các số (theo mô-đun) nhỏ hơn số nhỏ này, thì chúng được coi là bằng nhau. Ví dụ:
a = 0.00000000012
b = 0.000000000011
if abs(a - b) < 0.00001:
print("bằng nhau")
else:
print("không bằng nhau")
GO TO FULL VERSION