Lỗi dấu chấm động python

Bạn đã bao giờ gặp phải các vấn đề kỳ lạ khi làm việc với các số dấu phẩy động - chẳng hạn như khi thực hiện thao tác nào đó như sau?

a = 10b = 0.1c = 0.2a*(b+c) == a*b + a*c # This will print False

Đợi đã, cái gì?

Hãy xem một ví dụ khác

>>> .2 + .2 + .2 == .6False

Hoặc hãy xem vòng lặp này - nó sẽ chạy vô thời hạn

foo = 0while foo != 1.0:    foo = foo + 0.1print(foo)

Chuyện Gì Đang Xảy Ra?

TL; DR — Số dấu phẩy động thật kỳ lạ

Số dấu phẩy động hoạt động khá kỳ lạ trên các hệ thống nhị phân. Do đó, điều quan trọng là bạn nhận thức được hành vi này. Tôi sẽ giúp bạn tránh những sai lầm đơn giản có thể bỏ qua, chẳng hạn như một vòng lặp vô tận hoặc chỉ so sánh cơ bản

Dấu phẩy động là một kiểu đơn giản được tích hợp sẵn do Python cung cấp. Nó được gọi là kiểu đơn giản trái ngược với một số kiểu phức hợp như danh sách, tuple, dict và set. Số dấu phẩy động có thể lưu trữ các số phân số. Nó có thể được xác định trong ký hiệu thập phân tiêu chuẩn hoặc ký hiệu hàm mũ

máy tính. nhà phát triển

Ký hiệu thập phân chuẩn và ký hiệu hàm mũ

Trong ký hiệu số mũ, có thể đọc e hoặc E ". lần mười đến. ", do đó 1.4e6 được hiểu là 1. 4×10^6

Một số nguyên có thể được chuyển đổi rõ ràng thành số float với hàm tạo float

Bây giờ chúng ta đã biết biểu diễn dấu phẩy động trong python, hãy chuyển sang một số lỗi Độ chính xác của dấu phẩy động

Bình đẳng không ổn định

thận trọng. Độ chính xác số học của dấu phẩy động bị hạn chế. *, điều này có thể khiến các bài kiểm tra đẳng thức không ổn định. Ví dụ

* Độ chính xác số học của dấu phẩy động bị hạn chế. Tại sao điều này là trường hợp? . Tất cả các ngôn ngữ lập trình sử dụng số dấu phẩy động lưu trữ chúng trong một số bit cố định và điều này dẫn đến một số số chỉ được biểu diễn gần đúng. Chúng ta có thể thấy điều này bằng cách in ba giá trị với độ chính xác cao

Chúng ta thường thấy các số ở dạng ký hiệu thập phân (cơ số 10), sao cho mỗi phân số được biểu diễn dưới dạng tổng các lũy thừa của 10

Đại diện cơ sở 10

Trên đây là biểu diễn cơ số 10, chúng tôi biểu diễn điều này trong biểu thức thập phân là. 0. 125

Máy tính thường lưu trữ các giá trị trong ký hiệu nhị phân, do đó mỗi số được biểu thị dưới dạng tổng lũy ​​thừa của 2

Đại diện cơ sở 2

Trong biểu diễn cơ số 2, chúng ta có thể viết 0 này. 001, Giá trị 0. 125=0. 001 xảy ra là một số mà cả ký hiệu nhị phân và thập phân đều có thể biểu thị bằng một số chữ số hữu hạn

Trong biểu diễn cơ số 10 của các số, có lẽ bạn đã quen thuộc với các số không thể biểu thị bằng một số hữu hạn chữ số. Ví dụ: chia 1 cho 3, theo ký hiệu thập phân chuẩn

Thương số vô hạn cho ký hiệu thập phân

3s kéo dài mãi mãi. nghĩa là, vô số chữ số được yêu cầu để thực sự đại diện cho thương số này

Tương tự, có những số mà biểu diễn nhị phân yêu cầu vô số chữ số. Ví dụ

Thương số vô hạn cho ký hiệu nhị phân

Giống như ký hiệu thập phân yêu cầu vô số chữ số để biểu thị hoàn hảo 1/3, ký hiệu nhị phân yêu cầu vô số chữ số để biểu thị 1/10. Python nội bộ cắt bớt các biểu diễn này ở 52 bit ngoài bit khác không đầu tiên trên hầu hết các hệ thống. Cách tốt nhất để giải quyết vấn đề này là luôn ghi nhớ rằng số học dấu phẩy động là gần đúng và không bao giờ dựa vào các phép kiểm tra đẳng thức chính xác với các giá trị dấu phẩy động

Lỗi làm tròn chính xác

Nếu chúng ta cố gắng làm tròn giá trị 2. 675 đến hai chữ số thập phân chúng tôi nhận được. 2. 67

Tài liệu về hàm tích hợp nói rằng nó làm tròn đến giá trị gần nhất, làm tròn các mối quan hệ từ 0. Vì phân số thập phân 2. 675 chính xác nằm giữa 2. 67 và 2. 68, bạn có thể mong đợi kết quả ở đây là 2. 68. Không phải đâu, vì khi chuỗi thập phân 2. 675 được chuyển đổi thành số dấu phẩy động nhị phân, nó lại được thay thế bằng xấp xỉ nhị phân, có giá trị chính xác là,

Vì xấp xỉ này hơi gần với 2. 67 so với 2. 68, nó được làm tròn xuống

Một giải pháp để xử lý sự không nhất quán này trong giá trị dấu phẩy động là sử dụng mô-đun Python gốc có tên Decimal

Mô-đun thập phân

Sử dụng Decimal, chúng ta có thể thấy giá trị chính xác được lưu trữ trong bất kỳ float Python nào

Bạn cần cẩn thận khi sử dụng các giá trị Decimal() với kiểu float sẵn có, trừ khi được xử lý đúng cách, nó sẽ dẫn đến lỗi Loại

Nhập lỗi khi thêm giá trị Decimal() và giá trị float

quantize() để giải quyết Lỗi làm tròn chính xác

Làm tròn dấu phẩy động bằng cách sử dụng quantize() và round()

normalize() để ánh xạ các biểu diễn dấu phẩy động khác nhau thành một biểu diễn duy nhất

Một số ứng dụng có thể muốn có độ chính xác cố định cho tất cả các phép tính số học. Điều này có thể đạt được bằng cách sử dụng getcontext(). prec, điều này sẽ hạn chế các vị trí chính xác lên đến các giá trị đã đặt (giá trị chính xác mặc định là 28)

Phần kết luận

Lỗi làm tròn đối với các giá trị dấu phẩy động là một lỗi cần thiết khi làm việc với các số dấu phẩy động. Do đó, chúng ta sẽ không bao giờ quên thực tế rằng các số dấu phẩy động là giá trị gần đúng nhưng không phải là giá trị chính xác.

Tại sao Python float không chính xác?

Các phép tính dấu phẩy động không chính xác vì chủ yếu là các số hữu tỉ là xấp xỉ không thể biểu diễn hữu hạn trong cơ số 2 và nói chung chúng là xấp xỉ .

Lỗi ngoại lệ dấu phẩy động là gì?

Ngoại lệ dấu phẩy động (được bán phá giá lõi) là lỗi phát sinh khi ứng dụng của bạn cố gắng thực hiện điều gì đó không được phép với số dấu phẩy động.

Kiểu float trong Python 3 có thể biểu thị số thập phân 0 không. 1 mà không có lỗi?

Một số giá trị không thể được biểu diễn chính xác trong kiểu dữ liệu float. Chẳng hạn, lưu trữ 0. 1 trong biến float (là giá trị dấu phẩy động nhị phân), chúng ta chỉ nhận được giá trị gần đúng . Tương tự, giá trị 1/3 không thể được biểu diễn chính xác theo kiểu dấu chấm động thập phân.

Tại sao 0. 1 0. 2 không phải là 0. 3 con trăn?

Tương tự, giá trị nhị phân của 0. 2 được lưu dưới dạng 0. 001100110. Bây giờ, khi bạn thêm 0. 1 + 0. 2 bằng Python (hoặc bằng một số ngôn ngữ lập trình khác), Python chuyển đổi 0. 1 và 0. 2 về dạng nhị phân. Sau đó, nó thực hiện phép cộng. Kết quả sẽ không bao giờ bằng 0. 3 chính xác .