Câu hỏi Giới hạn nổi hai điểm thập phân


tôi muốn a được làm tròn thành 13,95.

>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999

Các round chức năng không hoạt động theo cách tôi mong đợi.


1126
2018-01-18 18:16


gốc


stackoverflow.com/questions/249467/…
Hmm ... Bạn đang cố gắng đại diện cho tiền tệ? Nếu vậy, bạn không nên sử dụng phao cho đô la. Bạn có thể sử dụng phao nổi cho đồng xu, hoặc bất kỳ đơn vị tiền tệ phổ biến nhỏ nhất nào bạn đang cố gắng mô hình xảy ra, nhưng thực hành tốt nhất là sử dụng một biểu diễn thập phân, như HUAGHAGUAH gợi ý trong câu trả lời của ông. - SingleNegationElimination
Điều quan trọng là không đại diện cho tiền tệ trong phao. Nổi không chính xác. Nhưng số tiền xu hoặc xu là số nguyên. Do đó các số nguyên là cách chính xác để biểu diễn tiền tệ. - Davoud Taghawi-Nejad
Tôi đến đây có lẽ đã quá muộn, nhưng tôi muốn hỏi, các nhà phát triển Python có giải quyết được vấn đề này không? Bởi vì khi tôi làm tròn (13.949999999999999, 2), tôi chỉ đơn giản nhận được 13,95. Tôi đã thử nó trong Python 2.7.6, cũng như 3.4. Nó hoạt động. Không chắc chắn nếu 2,7 thậm chí đã có trong năm 2009. Có lẽ đó là một điều 2,5 Python? - bad_keypoints
@bad_keypoints: Có, vấn đề làm tròn đã được giải quyết bằng Python 2.7.0+. Thêm trong câu trả lời của tôi đây - hynekcer


Các câu trả lời:


Bạn đang chạy vào vấn đề cũ với các số dấu phẩy động mà tất cả các số không thể được biểu diễn. Dòng lệnh chỉ hiển thị cho bạn mẫu dấu chấm động đầy đủ từ bộ nhớ.

Trong điểm nổi, phiên bản làm tròn của bạn là cùng một số. Vì các máy tính là nhị phân, chúng lưu trữ các số dấu phẩy động dưới dạng một số nguyên và sau đó chia số đó thành một lũy thừa của hai vì vậy 13.95 sẽ được biểu diễn theo kiểu tương tự với 125650429603636838 / (2 ** 53).

Số chính xác gấp đôi có 53 bit (16 chữ số) độ chính xác và các phao thông thường có độ chính xác 24 bit (8 chữ số). Các dấu chấm động trong Python sử dụng độ chính xác gấp đôi để lưu trữ các giá trị.

Ví dụ,

  >>> 125650429603636838/(2**53)
  13.949999999999999

  >>> 234042163/(2**24)
  13.949999988079071

  >>> a=13.946
  >>> print(a)
  13.946
  >>> print("%.2f" % a)
  13.95
  >>> round(a,2)
  13.949999999999999
  >>> print("%.2f" % round(a,2))
  13.95
  >>> print("{0:.2f}".format(a))
  13.95
  >>> print("{0:.2f}".format(round(a,2)))
  13.95
  >>> print("{0:.15f}".format(round(a,2)))
  13.949999999999999

Nếu bạn chỉ sau hai chữ số thập phân như tiền tệ thì bạn có một vài lựa chọn tốt hơn: 1) Sử dụng số nguyên và giá trị lưu trữ theo xu, không phải đô la và sau đó chia cho 100 để chuyển đổi thành đô la. 2) Hoặc sử dụng số điểm cố định như số thập phân.


1161
2018-01-18 18:23



@Christian Có sự khác biệt cơ bản giữa giá trị được lưu trữ và cách bạn trưng bày giá trị đó. Định dạng đầu ra sẽ cho phép bạn thêm đệm theo yêu cầu, cũng như thêm dấu phẩy phân cách, v.v. - Basic
đáng nói đến "%.2f" % round(a,2) bạn có thể đặt vào không chỉ trong printf, mà còn ở những thứ như vậy str() - andilabs
tại sao mọi người luôn giả định tiền tệ làm tròn điểm nổi? đôi khi bạn chỉ muốn làm việc với độ chính xác thấp hơn. - worc
@radtek: Bạn cần hiểu rằng giá trị nhị phân (thuộc loại float) chỉ là xấp xỉ gần nhất có sẵn của số thập phân (mà bạn đã quen thuộc với tư cách là con người). Không có giá trị nhị phân (có thể biểu diễn) như 0.245. Nó đơn giản không tồn tại, và toán học không thể hiện hữu. Giá trị nhị phân gần 0,245 nhất là hơi ít hơn 0.245, tự nhiên nó tròn xuống. Tương tự như vậy, không có điều gì như 0,225 trong nhị phân, nhưng giá trị nhị phân gần nhất là 0,225 là hơi lớn hơn 0.225, tự nhiên nó tròn lên. - John Y
@radtek: Bạn đã thực sự yêu cầu một lời giải thích. Giải pháp đơn giản nhất thực sự là sử dụng Decimalvà đó là một trong những giải pháp được trình bày trong câu trả lời này. Khác là chuyển đổi số lượng của bạn thành số nguyên và sử dụng số học số nguyên. Cả hai cách tiếp cận này cũng xuất hiện trong các câu trả lời và nhận xét khác. - John Y


Có các thông số định dạng mới, Đặc điểm kỹ thuật định dạng chuỗi Mini-Language:

Bạn có thể làm tương tự như:

"{0:.2f}".format(13.949999999999999)

chú thích rằng ở trên trả về một chuỗi. Để nổi lên, chỉ cần quấn bằng float(...):

float("{0:.2f}".format(13.949999999999999))

chú thích gói với float() không thay đổi gì cả:

>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{0:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True

423
2018-06-30 18:53



Điều đó sẽ cho bạn một chuỗi. Không phải là một con số. - Onur Yıldırım
để thêm dấu phẩy, bạn có thể '{0:,.2f}'.format(1333.949999999) bản in nào '1,333.95'. - Stephen Blum
@ OnurYıldırım: có, nhưng bạn có thể kết hợp nó với float(); float("{0:.2f}".format(13.9499999)) - Jossef Harush
@JossefHarush bạn có thể quấn nó với float (), nhưng bạn đã không đạt được bất cứ điều gì. Bây giờ bạn có một phao một lần nữa, với tất cả cùng một sự không chính xác. 13.9499999999999 và 13.95 là cùng một phao. - Ned Batchelder
@NedBatchelder: tôi đồng ý rằng chúng bằng nhau, nhưng điều này giới hạn phao đến hai dấu thập phân :) - Jossef Harush


Tích hợp sẵn round() hoạt động tốt trong Python 2.7 hoặc mới hơn.

Thí dụ:

>>> round(14.22222223, 2)
14.22

Kiểm tra tài liệu.


143
2017-12-31 10:51



Vì vậy, tôi có hiểu rằng đây là một Python 2,7 thất bại? Tại sao một hàm cơ bản như vậy lại mang lại các kết quả khác nhau từ v 2.7 đến v 3? - Michael Mügge
nhưng round(2.16, 1) đưa cho 2.2 tại sao python chỉ cung cấp truncate func - jiamo
Điều này cũng hoạt động trong Python 2.7. Câu trả lời hay nhất cho câu hỏi này, theo ý kiến ​​của tôi. - alwbtc


Tôi cảm thấy rằng cách tiếp cận đơn giản nhất là sử dụng format() chức năng.

Ví dụ:

a = 13.949999999999999
format(a, '.2f')

13.95

Điều này tạo ra một số phao như một chuỗi được làm tròn đến hai dấu thập phân.


118
2018-01-25 22:26



lưu ý rằng kiểu trả về của chuỗi này sẽ là một chuỗi. đây không phải là những gì tôi đang tìm kiếm. - Dap
@Dap float(format(a, '.2f')) - T. Webster


Hầu hết các số không thể được biểu diễn chính xác trong phao. Nếu bạn muốn làm tròn số vì đó là những gì công thức toán học hoặc thuật toán của bạn yêu cầu, thì bạn muốn sử dụng vòng. Nếu bạn chỉ muốn hạn chế hiển thị với độ chính xác nhất định, thì thậm chí không sử dụng vòng và chỉ định dạng nó thành chuỗi đó. (Nếu bạn muốn hiển thị nó với một số phương pháp làm tròn thay thế, và có tấn, sau đó bạn cần phải kết hợp hai phương pháp tiếp cận.)

>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'

Và cuối cùng, mặc dù có lẽ quan trọng nhất, nếu bạn muốn chính xác toán học thì bạn không muốn phao nổi. Ví dụ thông thường là xử lý tiền và lưu trữ 'xu' làm số nguyên.


85
2018-01-18 18:40





Hãy thử mã dưới đây:

>>> a = 0.99334
>>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
>>> print a
0.99

65
2017-08-26 06:46



Nhưng được cảnh báo, giá trị của một vẫn là một phao không chính xác. Hãy xem ở đây - repl.it/LJs (Nhấp vào "Chạy phiên" ở trên cùng của phần bên phải). - lifebalance
Nếu bạn đi với phương pháp này, bạn nên thêm một 0,5 cho một đại diện chính xác hơn. int (a * 100 + 0.5) / 100.0; Sử dụng math.ceil là một tùy chọn khác. - arhuaco
@ShashankSawant: Vâng, đối với một điều, câu trả lời như trình bày không tròn, nó cắt ngắn. Đề xuất để thêm một nửa vào cuối sẽ tròn, nhưng sau đó không có lợi ích để làm điều này hơn chỉ bằng cách sử dụng round chức năng ở nơi đầu tiên. Đối với một điều khác, bởi vì giải pháp này vẫn còn sử dụng dấu chấm động, vấn đề ban đầu của OP vẫn còn, ngay cả đối với phiên bản "đã sửa" của giải pháp "" này. - John Y
-1, đây chỉ là một reimplementation không cần thiết của round chức năng (được sử dụng trong câu hỏi). - interjay
@interjay đó là cần thiết nếu round() không hoạt động như OP được đề cập. - Pithikos


Với Python <3 (ví dụ: 2.6 hoặc 2.7), có hai cách để làm như vậy.

# Option one 
older_method_string = "%.9f" % numvar

# Option two (note ':' before the '.9f')
newer_method_string = "{:.9f}".format(numvar)

Nhưng lưu ý rằng đối với các phiên bản Python trên 3 (ví dụ: 3.2 hoặc 3.3), tùy chọn hai là ưa thích.

Để biết thêm thông tin về tùy chọn hai, tôi đề xuất liên kết này trên định dạng chuỗi từ tài liệu Python.

Và để biết thêm thông tin về tùy chọn một, liên kết này sẽ đủ và có thông tin về các cờ khác nhau.

Tài liệu tham khảo: Chuyển đổi số dấu chấm động thành độ chính xác nhất định, sau đó sao chép thành chuỗi


49
2017-12-11 06:37



Làm thế nào để bạn đại diện cho một số nguyên? Nếu tôi sử dụng "{i3}" định dạng (numvar) tôi nhận được một lỗi. - skytux
Đây là những gì tôi có ý nghĩa: Nếu numvar=12.456, sau đó "{:.2f}".format(numvar) sản lượng 12.46 nhưng "{:2i}".format(numvar) đưa ra một lỗi và tôi đang mong đợi 12. - skytux


Bạn có thể sửa đổi định dạng đầu ra:

>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95

39
2018-01-18 18:31