CodeGym /Khóa học Java /Python SELF VI /Công việc với số thực

Công việc với số thực

Python SELF VI
Mức độ , Bài học
Có sẵn

4.1 Làm tròn số thực

Số thực (số thập phân) trong tiếng Anh gọi là floating 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ọc
  • round — vòng/làm tròn
  • ceiling — 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ố - 234567898. 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

1000000000.000000000
-     0.000000001
1000000000.000000000
                            
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")
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION