2014-09-29 15 views
12

Tôi chỉ đang xem xét một số khái niệm cơ bản về Python và có một vấn đề phức tạp khi so sánh các số dấu phẩy động.So sánh số dấu phẩy động của Python

2.2 * 3.0 == 6.6 
3.3 * 2.0 == 6.6 

Tôi nghĩ cả hai đều nên trả về Sai. Tuy nhiên, điều thứ hai đã cho tôi một sự thật. enter image description here

Vui lòng giúp tôi tại đây. Cảm ơn!

+10

Bạn sẽ không bao giờ so sánh hai số phao bằng '=='. Sử dụng 'abs (a-b) Steve

+0

@Steve Có, tôi biết điều đó, nhưng vẫn cảm ơn cho ghi chú của bạn :) – Zhiya

+3

@Steve: So sánh chính xác phức tạp hơn điều này, vì độ chính xác của phao là một số chữ số, không phải là giá trị số tuyệt đối. Một cái gì đó như 'abs (a-b) <= rel_prec * max (abs (a), abs (b))' là tốt hơn (với rel_prec gần 1e-16, ví dụ, đối với các float chính xác kép của Python). Thêm vào đó, trường hợp của một giá trị bằng không nên được xử lý quá. Tôi đã không kiểm tra đầy đủ điều này, nhưng sau đây có thể làm việc: 'abs (a-b) <= rel_prec * (tối đa (abs (a), abs (b)) nếu a! = 0! = B else 1)'. – EOL

Trả lời

11

Điều này có thể được chiếu sáng:

>>> float.hex(2.2 * 3.0) 
'0x1.a666666666667p+2' 
>>> float.hex(3.3 * 2.0) 
'0x1.a666666666666p+2' 
>>> float.hex(6.6) 
'0x1.a666666666666p+2' 

Mặc dù tất cả chúng đều được hiển thị trong thập phân như 6.6, khi bạn kiểm tra các đại diện bên trong, hai trong số họ được đại diện trong cùng một cách, trong khi một trong số họ không phải là.

+1

Nhưng chúng _not_ tất cả được hiển thị dưới dạng thập phân là '6,6'. Trong 3.x, 'print (2.2 * 3.0)' hoặc chỉ '2.2 * 3.0' sẽ hiển thị' 6.6000000000000005'. Trong 2.x, 'print' sẽ cắt ngắn, nhưng chỉ' 2.2 * 3.0' sẽ vẫn hiển thị '6.6000000000000005'. Vì vậy, điều này là đơn giản để xem hơn câu trả lời ngụ ý. – abarnert

+0

@abarnert: Ah, đúng vậy. Tôi giả định, không kiểm tra. – Amadan

2

Để hoàn thành câu trả lời hay của Amadan, đây là cách rõ ràng hơn để thấy rằng 2.2 * 3. và 3.3 * 2. không được đại diện bởi các phao giống nhau: trong một vỏ Python,

>>> 2.2 * 3. 
6.6000000000000005 
>>> 3.3 * 2. 
6.6 

Trong thực tế, Python vỏ hiển thị đại diện số, mà theo định nghĩa nên cho phép thả nổi tương ứng được xây dựng một cách chính xác lại từ các đại diện , vì vậy bạn thấy số xấp xỉ 2,2 * 3 mà Python thực hiện. Thực tế là 2,2 * 3. ! = 3.3 * 2. là hiển nhiên khi nhìn thấy tất cả các chữ số cần thiết, như trên.

+0

Phần về biểu diễn so với phiên bản thân thiện có liên quan đến Python 2.x, nhưng không phải là 3.x. Trong 3.x, 'print (2.2 * 3.)' Sẽ vẫn cung cấp cho bạn '6.6000000000000005'. Trong 3.x, cả hai 'str' và' repr' trả về chuỗi ngắn nhất sẽ đánh giá về cùng 'float'; trong 2.x, 'str' cắt ngắn thành số chữ số cụ thể theo nền tảng, trong khi' repr' thì không. – abarnert

+0

Thú vị. Không có "một phần về biểu diễn so với phiên bản thân thiện" trước bình luận của bạn. : D – EOL

+1

Tham khảo về thay đổi 'str' của Python 3: http://stackoverflow.com/questions/25898733/why-does-strfloat-return-more-digits-in-python-3-than-python-2. – EOL

Các vấn đề liên quan