2015-07-07 22 views
7

Nếu tôi nói với Python v. 3.4.3, round(2.5), thì nó sẽ xuất ra 2. Nếu tôi nói với nó là round(1.5) thì nó cũng xuất ra 2. Tương tự, round(3.5) cung cấp cho 4, trong khi round(4.5) cũng cung cấp cho 4. Tôi cần Python để tròn với nhất quán, mặc dù. Cụ thể, nó cần phải tròn bất cứ lúc nào tôi nhập vào một số giữa hai số nguyên. Vì vậy, round(1.5) = 1round(2.5) = 2, trong khi round(1.6) = 2 và như vậy, như thường lệ.Làm tròn Python không nhất quán

Tôi làm cách nào để giải quyết vấn đề này?

EDIT: Tôi đã đọc tài liệu về chức năng round và hiểu rằng đây là hành vi dự định của nó. Câu hỏi của tôi là, làm thế nào tôi có thể thay đổi hành vi này, bởi vì với mục đích của tôi, tôi cần 1,5 vòng xuống.

+3

bản sao có thể có của [Hành vi làm tròn Python 3.x] (http://stackoverflow.com/questions/10825926/python-3-x-rounding-behavior) – tzaman

+0

Lưu ý rằng đây không phải là hoàn toàn trùng lặp: OP là chủ yếu là nhầm lẫn bằng cách Python 3 viên đạn, không phải bằng cách nó đã thay đổi từ Python 2. – Evert

+0

Đây là một quan sát quan trọng đối với hầu hết người mới sử dụng Python. Mặc dù đáng ngạc nhiên lúc đầu, Python 3 vòng nhiều [nhất quán hơn bạn nghĩ] (http://stackoverflow.com/a/40376443/2932052). – Wolf

Trả lời

2

Python 3 sử dụng hành vi làm tròn khác so với Python 2: bây giờ sử dụng cái gọi là "làm tròn của ngân hàng" (Wikipedia): khi phần nguyên là số lẻ, số được làm tròn từ 0; khi phần nguyên là chẵn, nó được làm tròn về không.

Lý do cho điều này là để tránh thiên vị, khi tất cả các giá trị tại .5 được làm tròn từ 0 (và sau đó ví dụ: tổng kết).

Đây là hành vi bạn đang thấy và thực tế là nhất quán. Nó có lẽ chỉ khác với những gì bạn đang sử dụng.

+0

Nó không thực sự là một vấn đề làm quen với nó. Đối với các ứng dụng của tôi, tôi thực sự * cần * nó luôn luôn tròn số như 1,5, 2,5, 3,5, ... xuống. Có cách nào để sửa đổi chức năng 'round' để làm điều này không? –

+0

@JamesPirlman Nếu bạn cần các hành vi cụ thể khi xử lý các số không nguyên, bạn thực sự cần sử dụng [Mô-đun thập phân] (https://docs.python.org/3/library/decimal.html), như tôi và những người khác đã đề cập. Đây không phải là về 'round' cụ thể, nhưng cách các máy tính xử lý các số dấu phẩy động nói chung. [Xem câu trả lời của tôi] (http://stackoverflow.com/a/31258564/2194039). – justinpawela

+0

* "cái gọi là" làm tròn của ngân hàng "' * nên được thay thế bằng cái gì đó chính xác hơn cho ngữ cảnh này, nó được định nghĩa trong IEEE-754, Wikipedia nói * 'Đây là chế độ làm tròn mặc định được sử dụng trong các chức năng tính toán IEEE 754 và toán tử (xem thêm hàm nguyên gần nhất) .' * – Wolf

1

Đây là tài liệu khá tốt. Theo số Python docs for round:

Lưu ý Hành vi của vòng() cho nổi có thể gây ngạc nhiên: ví dụ, vòng (2.675, 2) cho 2,67 thay vì mong đợi 2,68. Đây không phải là lỗi: đó là kết quả của thực tế là hầu hết các phân số thập phân không thể được biểu diễn chính xác dưới dạng phao. Xem Floating Point Arithmetic: Issues and Limitations để biết thêm thông tin

Cụ thể, đây là tác dụng phụ của cách máy tính xử lý các số dấu phẩy động nói chung.

Nếu bạn cần chính xác hơn, bao gồm làm tròn khác nhau, tôi khuyên bạn nên kiểm tra the Python Decimal module. Đặc biệt quan tâm, họ có khả năng kiểm soát rounding modes. Có vẻ như bạn có thể muốn decimal.ROUND_HALF_DOWN.

3

round docs làm địa chỉ các đặc tính làm tròn số dấu phẩy động.

Bạn có thể sử dụng thư viện decimal để đạt được những gì bạn muốn.

from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_DOWN 

round(2.675, 2) 
# output: 2.67 

Decimal('2.675').quantize(Decimal('1.11'), rounding=ROUND_HALF_UP) 
# output: 2.68 

Decimal('2.5').quantize(Decimal('1.'), rounding=ROUND_HALF_DOWN) 
# output: 2 
3

Bạn muốn "khoanh tròn" và bạn đang nhận được "tròn đến cả". Chỉ cần thực hiện theo cách thủ công bằng cách thực hiện

ceil(x - 0.5) 
+0

Câu trả lời hay cho câu hỏi cập nhật, tôi muốn upvote nó, nhưng tôi tìm thấy một từ về chủ đề ban đầu bị thiếu cho điều đó. – Wolf

0

Tôi tin rằng tôi có câu trả lời cho tất cả các lỗi làm tròn mà mọi người gặp phải. Tôi đã viết phương pháp của riêng tôi, có chức năng giống như "vòng" nhưng thực sự nhìn vào chữ số cuối cùng và vòng từ trường hợp đó theo từng trường hợp. Không có chuyển đổi một số thập phân sang nhị phân. Nó có thể xử lý bất kỳ số lượng các số sau dấu thập phân và nó cũng có ký hiệu khoa học (như xuất ra bởi phao). Nó cũng không yêu cầu bất kỳ hàng nhập khẩu nào! Hãy cho tôi biết nếu bạn bắt gặp bất kỳ trường hợp nào không hoạt động!

def Round(Number,digits = 0): 
Number_Str = str(Number) 
if "e" in Number_Str: 
    Number_Str = "%.10f" % float(Number_Str) 
if "." in Number_Str: #If not given an integer 
    try: 
     Number_List = list(Number_Str) #All the characters in Number in a list 
     Number_To_Check = Number_List[Number_List.index(".") + 1 + digits] #Gets value to be looked at for rounding.  
     if int(Number_To_Check) >= 5: 
      Index_Number_To_Round = Number_List.index(".") + digits 
      if Number_List[Index_Number_To_Round] == ".": 
       Index_Number_To_Round -= 1 
      if int(Number_List[Index_Number_To_Round]) == 9: 
       Number_List_Spliced = Number_List[:Number_List.index(".")+digits] 
       for index in range(-1,-len(Number_List_Spliced) - 1,-1): 
        if Number_List_Spliced[index] == ".": 
         continue 
        elif int(Number_List_Spliced[index]) == 9: 
         Number_List_Spliced[index] = "0" 
         try: 
          Number_List_Spliced[index-1] 
          continue 
         except IndexError: 
          Number_List_Spliced.insert(0,"1") 
        else: 
         Number_List_Spliced[index] = str(int(Number_List_Spliced[index])+1) 
         break 
       FinalNumber = "".join(Number_List_Spliced) 
      else: 
       Number_List[Index_Number_To_Round] = str(int(Number_List[Index_Number_To_Round])+1) 
       FinalNumber = "".join(Number_List[:Index_Number_To_Round + 1]) 
      return float(FinalNumber) 
     else: 
      FinalNumber = "".join(Number_List[:Number_List.index(".") + 1 + digits]) 
      return float(FinalNumber) 
    except IndexError: 
     return float(Number) 
else: #If given an integer 
    return float(Number) 
0

Python 3 cung cấp phương pháp làm tròn được định nghĩa trong IEEE Standard for Floating-Point Arithmetic (IEEE 754), mặc định làm tròn [1] được chuyển trực tiếp tới số gần nhất và giảm thiểu lỗi tích lũy.

Trong IEEE 754, có 5 phương pháp xác định, hai để làm tròn đến gần (Python cung cấp một đầu tiên bởi round) và ba phương pháp mà đạo rõ ràng (Python có trunc, ceil, và floor trong của nó Math mô-đun).

Bạn rõ ràng cần phải làm tròn hướng dẫn và có cách để nói với Python này, bạn phải chọn.


[1] Kể từ khi các đại diện của các số dấu phảy trong máy tính là có hạn, làm tròn không phải là tầm thường như bạn nghĩ, bạn sẽ ngạc nhiên! Tôi khuyên bạn nên đọc kỹ số 15. Floating Point Arithmetic: Issues and Limitations trong tài liệu python 3.

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