2014-09-17 32 views
17

Trong Python 2.7, repr của số float trả lại số thập phân gần nhất dài tối đa 17 chữ số; điều này là chính xác, đủ để xác định duy nhất mỗi giá trị điểm nổi có thể của IEEE. str của một float hoạt động tương tự, ngoại trừ việc nó giới hạn kết quả là 12 chữ số; đối với hầu hết các mục đích, đây là kết quả hợp lý hơn và cách ly bạn khỏi những khác biệt nhỏ giữa biểu diễn nhị phân và số thập phân.Tại sao str (float) trả lại nhiều chữ số trong Python 3 hơn Python 2?

Python 2 demo: http://ideone.com/OKJtxv

print str(1.4*1.5) 
2.1 
print repr(1.4*1.5) 
2.0999999999999996 

Trong Python 3.2 nó xuất hiện strrepr trả lại điều tương tự.

Python 3 demo: http://ideone.com/oAKRsb

print(str(1.4*1.5)) 
2.0999999999999996 
print(repr(1.4*1.5)) 
2.0999999999999996 

Có PEP mô tả sự thay đổi, hoặc một số tuyên bố khác từ một người chịu trách nhiệm?

+2

Có vẻ như vấn đề [# 1580] (http://bugs.python.org/issue1580) có thể có liên quan ở đây. Cũng có một lưu ý về thay đổi này trong [Có gì mới trong Python 3.1: Các thay đổi ngôn ngữ khác] (https://docs.python.org/3/whatsnew/3.1.html#other-language-changes) (điểm bullet cuối cùng). –

+6

Tôi đoán đây là cái này: http://bugs.python.org/issue9337 – georg

+0

Python 3.1 đã thêm một tính năng mới để ẩn các lỗi làm tròn không liên quan bằng cách làm tròn thành phần thập phân _shortest_ trong một epsilon của float, thay vì _closest_, do đó, việc xóa 12 chữ số không còn cần thiết nữa. – abarnert

Trả lời

25

Không, không có PEP. Có một issue trong trình theo dõi lỗi và associated discussion trên danh sách gửi thư của nhà phát triển Python. Trong khi tôi chịu trách nhiệm đề xuất và thực hiện thay đổi, tôi không thể khẳng định đó là ý tưởng của tôi: nó đã nảy sinh trong các cuộc trò chuyện với Guido tại EuroPython 2010.

Một số chi tiết khác: như đã đề cập trong các nhận xét, Python 3.1 đã giới thiệu thuật toán mới cho chuỗi repr của một phao, (sau này được quay trở lại chuỗi Python 2, để nó cũng xuất hiện trong Python 2.7). Kết quả của thuật toán mới này, một số thập phân "ngắn" được nhập vào tại dấu nhắc có một biểu diễn ngắn tương ứng. Điều này đã loại bỏ một trong những lý do hiện tại cho sự khác biệt giữa strrepr và có thể sử dụng cùng một thuật toán cho cả hai strrepr. Vì vậy, đối với Python 3.2, theo các cuộc thảo luận được liên kết ở trên, strrepr đã được thực hiện giống hệt nhau. Về lý do: nó làm cho ngôn ngữ nhỏ hơn và sạch hơn một chút, và nó loại bỏ sự lựa chọn thay vì tùy ý 12 chữ số khi xuất chuỗi. (Sự lựa chọn 17 chữ số được sử dụng cho repr trong các phiên bản Python trước 2.7 là xa tùy ý, bằng cách này: hai riêng biệt IEEE 754 binary64 float sẽ có biểu diễn riêng biệt khi chuyển đổi sang thập phân với 17 chữ số có nghĩa, và 17 là số nguyên nhỏ nhất với thuộc tính này.)

Ngoài sự đơn giản, có một số lợi ích ít rõ ràng hơn. Một khía cạnh của sự khác biệt repr so với str gây nhầm lẫn cho người dùng trong quá khứ là thực tế là repr tự động được sử dụng trong vùng chứa. Vì vậy, ví dụ như trong Python 2.7:

>>> x = 1.4 * 1.5 
>>> print x 
2.1 
>>> print [x] 
[2.0999999999999996] 

Tôi chắc rằng có ít nhất một câu hỏi StackOverflow hỏi về hiện tượng này ở đâu đó: here is one such, và nhiều hơn nữa another một gần đây. Với việc đơn giản hóa được giới thiệu trong Python 3.2, chúng tôi nhận được điều này thay thế:

>>> x = 1.4 * 1.5 
>>> print(x) 
2.0999999999999996 
>>> print([x]) 
[2.0999999999999996] 

ít nhất là nhất quán hơn.

Nếu bạn muốn có thể ẩn các trường hợp không chính xác, cách đúng để thực hiện nó vẫn giữ nguyên: sử dụng định dạng chuỗi để điều khiển chính xác định dạng đầu ra.

>>> print("{:.12g}".format(x)) 
2.1 

Tôi hy vọng giải thích một số lý do đằng sau thay đổi. Tôi sẽ không tranh luận rằng nó mang lại lợi ích chung: như bạn chỉ ra, cái cũ str có tác dụng phụ thuận lợi của việc che giấu những sự không chính xác. Nhưng theo ý kiến ​​của tôi (tất nhiên, tôi thiên vị), nó giúp loại bỏ một số bất ngờ từ ngôn ngữ.

+0

Cảm ơn thông tin, đây chính xác là những gì tôi đang tìm kiếm. Tôi chỉ ước rằng có tương đương với thông số định dạng 'g' không tự ý chuyển sang ký pháp khoa học, tôi tránh nó vì lý do đó. –

+0

Đồng ý; Tôi thường muốn định dạng chuỗi được cấu hình nhiều hơn một chút. Một ngày nào đó, có thể. –

+0

P.S. Tôi không chắc chắn tôi mua các đối số rằng đầu ra của một đối tượng cần phải giống như đầu ra của một danh sách chứa đối tượng, đó là * vẫn * không phải là trường hợp cho các chuỗi chứa các ký tự không thể in được: http://ideone.com/zNauZB –

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