Giới hạn số float đến hai điểm thập phân


1691

Tôi muốn ađược làm tròn đến 13,95 .

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

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



6
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ể có thể sử dụng phao cho đồng xu, hoặc bất kỳ đơn vị tiền tệ phổ biến nhỏ nhất mà bạn đang cố gắng tạo ra, nhưng cách tốt nhất là sử dụng biểu diễn thập phân, như HUAGHAGUAH đã đề xuất trong câu trả lời của anh ấy.
SingleNegationElimination

63
Điều quan trọng là không đại diện cho tiền tệ trong float. Phao không chính xác. Nhưng số tiền hoặc xu là số nguyên. Do đó, số nguyên là cách chính xác để thể hiện tiền tệ.
Davoud Taghawi-Nejad

2
@ DavoudTaghawi-Nejad hoặc hơn thế nữa ... Loại thập phân
Cơ bản

17
Có lẽ tôi đến quá muộn ở đây, nhưng tôi muốn hỏi, các nhà phát triển của Python đã giải quyết vấn đề này chưa? 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 Python 2.5?
bad_keypoint

Câu trả lời:


1690

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

Với biểu diễn dấu phẩy động, phiên bản 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 nó cho lũy thừa của hai nên 13,95 sẽ được biểu diễn theo kiểu tương tự như 125650429603636838 / (2 ** 53).

Số chính xác kép có độ chính xác 53 bit (16 chữ số) và phao thông thường có độ chính xác 24 bit (8 chữ số). Kiểu dấu phẩy động trong Python sử dụng độ chính xác kép để 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("{:.2f}".format(a))
13.95
>>> print("{:.2f}".format(round(a, 2)))
13.95
>>> print("{:.15f}".format(round(a, 2)))
13.949999999999999

Nếu bạn chỉ sau hai vị trí thập phân (để hiển thị giá trị tiền tệ chẳng hạn), thì bạn có một vài lựa chọn tốt hơn:

  1. Sử dụng số nguyên và lưu trữ giá trị bằng xu, không phải đô la và sau đó chia cho 100 để chuyển đổi thành đô la.
  2. Hoặc sử dụng một số điểm cố định như số thập phân .

27
@Christian Có một sự khác biệt cơ bản giữa giá trị được lưu trữ và cách bạn hiển thị giá trị đó. Định dạng đầu ra sẽ cho phép bạn thêm phần đệm theo yêu cầu, cũng như thêm dấu tách dấu phẩy, v.v.
Cơ bản

22
đáng nói là "%.2f" % round(a,2)bạn có thể đưa vào không chỉ trong printf, mà còn trong những thứ nhưstr()
andilabs

20
Tại sao mọi người luôn giả định tiền tệ trong 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

9
@radtek: Bạn cần hiểu rằng giá trị nhị phân (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à một con người). Không có giá trị nhị phân (có thể biểu diễn chính xác) như 0,245. Nó chỉ đơn giản là không tồn tại, và về mặt toán học không thể tồn tại. Giá trị nhị phân gần nhất với 0,245 nhỏ hơn 0,245 một chút , do đó, tự nhiên nó làm tròn xuống. Tương tự như vậy, không có thứ gọi là 0,225 trong nhị phân, nhưng giá trị nhị phân gần nhất với 0,225 lớn hơn 0,225 một chút , do đó, tự nhiên nó làm tròn lên.
John Y

12
@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 Decimal, và đó là một trong những giải pháp được trình bày trong câu trả lời này. Cách 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à bình luận khác.
John Y

586

Có các đặc tả định dạng mới, Đặc tả định dạng chuỗi Mini-Language :

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

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

Lưu ý 1: ở trên trả về một chuỗi. Để có được như float, chỉ cần bọc với float(...):

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

Lưu ý 2: gói float()không thay đổi bất cứ điều gì:

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

17
để thêm dấu phẩy, bạn có thể '{0:,.2f}'.format(1333.949999999)in '1,333.95'.
Stephen Blum

@ OnurYıldırım: có, nhưng bạn có thể gói nó với float(); float("{0:.2f}".format(13.9499999))
Jossef Harush

5
@JossefHarush bạn có thể gói nó bằng float (), nhưng bạn chưa thu được gì. Bây giờ bạn có một lần nữa, với tất cả sự thiếu quyết đoán. 13.9499999999999 và 13,95 là cùng một float.
Ned Batchelder

4
@NedBatchelder: tôi đồng ý rằng chúng bằng nhau, nhưng điều này giới hạn số float đến hai điểm thập phân :)
Jossef Harush

8
Nhân tiện, kể từ Python 3.6, chúng ta có thể sử dụng chuỗi f:f"Result is {result:.2f}"
Andrey Semakin

289

Tích hợp round()hoạt động tốt trong Python 2.7 trở lên.

Thí dụ:

>>> round(14.22222223, 2)
14.22

Kiểm tra các tài liệu .


1
Vậy tôi có hiểu rằng đây là một Python 2.7 thất bại không? Tại sao một hàm cơ bản như vậy mang lại kết quả khác nhau từ v 2.7 đến v 3?
MikeM

nhưng round(2.16, 1)đưa ra 2.2lý do tại sao trăn chỉ cung cấp một truncatefunc
jiamo

Ví dụ, nếu bạn cố gắng để làm tròn giá trị 2,675 đến hai chữ số thập phân, bạn có được điều này >>> round(2.675, 2) 2.67 docs.python.org/2/tutorial/floatingpoint.html
danger89

4
Từ trang tài liệu Python 3:Note The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.
Richard Dally

Lưu ý rằng nếu bạn cố gắng sử dụng phương pháp này để in ra một số như 1,00000 thì nó sẽ chỉ in ra 1.0, bất kể bạn chỉ định bao nhiêu điểm thập phân.
Josh Correia

142

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ố float dưới dạng một chuỗi được làm tròn đến hai điểm thập phân.


97

Sử dụng

print"{:.2f}".format(a)

thay vì

print"{0:.2f}".format(a)

Bởi vì cái sau có thể dẫn đến lỗi đầu ra khi cố gắng xuất nhiều biến (xem bình luận).


2
Thật vô nghĩa. Hai câu lệnh được đưa ra hoạt động giống hệt nhau trên Python 2.7 và chỉ có câu lệnh thứ hai là hợp lệ trên Python 2.6. (Cả hai câu lệnh đều không hợp lệ trong Python 3 hoặc Python <2.6.) Hình thức đầu tiên không có lợi thế ngoài sự ngắn gọn.
Mark Dickinson

1
Ý tôi là, in "{0: .2f} {0: .2f}". Định dạng (a, b) sẽ dẫn đến nhầm lẫn trong đầu ra - nó sẽ xuất giá trị 'a' hai lần. Trong khi in định dạng "{:. 2f} {: .2f}". (A, b) sẽ tạo ra các giá trị 'a' và 'b'.
Alexey Antonenko

2
Đối với Python 3, bạn chỉ cần thêm dấu ngoặc in (...). Và trong tất cả những gì tôi viết là đúng.
Alexey Antonenko

"Ý tôi là, in" {0: .2f} {0: .2f} ". Định dạng (a, b) sẽ dẫn đến nhầm lẫn trong đầu ra". Ah. Vâng, đó là một tuyên bố hoàn toàn khác! Có lẽ bạn nên chỉnh sửa câu trả lời của bạn? (Chẳng hạn "lỗi tăng" nghĩa là gì trong câu trả lời hiện tại? Bạn có thể đưa ra một ví dụ về trường hợp câu lệnh thứ hai đưa ra một ngoại lệ nhưng câu đầu tiên không?)
Mark Dickinson

3
Bạn sẽ có sau khi in ("{0: .2f} {1: .2f}". Định dạng (a, b)) nếu bạn có hai biến
Hovo

95

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 giới hạn hiển thị ở một độ chính xác nhất định, thì thậm chí không sử dụng vòng và chỉ định dạng nó dưới dạng 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ó hàng tấn, thì bạn cần kết hợp hai cách 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 toán chính xác thì bạn hoàn toàn không muốn nổi. Ví dụ thông thường là xử lý tiền và lưu trữ 'xu' dưới dạng số nguyên.


68

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

Nhưng hãy cẩn thận, giá trị của a vẫn là một sự nổi không chính xác. Hãy xem tại đây - repl.it/LJs (Nhấp vào "Chạy phiên" trên đầu phần bên phải).
tuổi thọ

3
Nếu bạn đi theo cách tiếp cận này, bạn nên thêm 0,5 để thể hiện chính xác hơn. int (a * 100 + 0,5) / 100.0; Sử dụng math.ceil là một lựa chọn khác.
arhuaco

3
@ShashankSawant: Chà, vì một điều, câu trả lời như được 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ẽ làm tròn, nhưng sau đó không có lợi ích gì khi thực hiện việc này chỉ bằng cách sử dụng roundhàm ở vị trí đầu tiên. Đối với một điều khác, bởi vì giải pháp này vẫn sử dụng dấu phẩy độ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

3
-1, đây chỉ là một sự thực hiện lại không cần thiết của roundhàm (được sử dụng trong câu hỏi).
interjay

4
@interjay là cần thiết nếu round()không hoạt động như OP đã đề cập.
Pithikos

57

TLDR;)

Vấn đề làm tròn số đầu vào / đầu ra đã được giải quyết dứt điểm bằng Python 2.7.03.1 .

Một số được làm tròn chính xác có thể được chuyển đổi qua lại một cách thuận nghịch:
str -> float() -> repr() -> float() ...hoặc Decimal -> float -> str -> Decimal
Loại thập phân không cần thiết cho việc lưu trữ nữa.


(Đương nhiên, nó có thể là cần thiết để làm tròn kết quả của bổ sung, trừ các số tròn để loại bỏ các lỗi bit cuối cùng tích lũy được. Một số thập phân số học rõ ràng có thể vẫn tiện dụng, nhưng một chuyển đổi chuỗi bằng str()(có nghĩa là với làm tròn đến 12 chữ số có giá trị ) là đủ tốt thường nếu không có độ chính xác cực cao hoặc không có số lượng cực lớn các phép toán số học liên tiếp được yêu cầu.)

Kiểm tra vô hạn :

import random
from decimal import Decimal
for x in iter(random.random, None):           # Verify FOREVER that rounding is fixed :-)
    assert float(repr(x)) == x                # Reversible repr() conversion.
    assert float(Decimal(repr(x))) == x
    assert len(repr(round(x, 10))) <= 12      # Smart decimal places in repr() after round.
    if x >= 0.1:                              # Implicit rounding to 12 significant digits
        assert str(x) == repr(round(x, 12))   # by str() is good enough for small errors.
        y = 1000 * x                             # Decimal type is excessive for shopping
        assert str(y) == repr(round(y, 12 - 3))  # in a supermaket with Python 2.7+ :-)

Tài liệu

Xem Ghi chú phát hành Python 2.7 - Ngôn ngữ khác Thay đổi đoạn thứ tư:

Chuyển đổi giữa các số dấu phẩy động và chuỗi hiện được làm tròn chính xác trên hầu hết các nền tảng. Các chuyển đổi này xảy ra ở nhiều nơi khác nhau: str () trên số float và số phức; các nhà xây dựng nổi và phức tạp; định dạng số; serializing và de-serializing phao nổi và các số phức bằng cách sử dụng marshal, picklejsonmodule; phân tích cú pháp float và chữ tưởng tượng trong mã Python; và chuyển đổi thập phân sang nổi.

Liên quan đến điều này, repr () của số dấu phẩy động x bây giờ trả về kết quả dựa trên chuỗi thập phân ngắn nhất được đảm bảo làm tròn trở lại x theo cách làm tròn chính xác (với chế độ làm tròn nửa tròn đến chẵn). Trước đây, nó đã đưa ra một chuỗi dựa trên làm tròn x đến 17 chữ số thập phân.

Vấn đề liên quan


Thông tin thêm: Định dạng floattrước Python 2.7 tương tự như hiện tại numpy.float64. Cả hai loại đều sử dụng cùng độ chính xác kép 64 bit của IEEE 754 với mantissa 52 bit. Một sự khác biệt lớn là np.float64.__repr__được định dạng thường xuyên với số thập phân quá mức để không mất bit nào, nhưng không tồn tại số IEEE 754 hợp lệ trong khoảng 13.949999999999999 và 13.950000000000001. Kết quả không đẹp và chuyển đổi repr(float(number_as_string))không thể đảo ngược với numpy. Mặt khác:float.__repr__được định dạng sao cho mọi chữ số đều quan trọng; trình tự là không có khoảng trống và chuyển đổi là đảo ngược. Đơn giản: Nếu bạn có thể có số numpy.float64, hãy chuyển đổi nó thành số float bình thường để được định dạng cho con người, không phải cho bộ xử lý số, nếu không thì không cần thêm gì với Python 2.7+.


Tại sao hạ cấp? Câu hỏi là về Python float(độ chính xác kép) và bình thường round, không phải về numpy.double và chuyển đổi thành chuỗi. Làm tròn Python đơn giản thực sự không thể được thực hiện tốt hơn trong Python 2.7. Hầu hết các câu trả lời đã được viết trước 2.7, nhưng chúng đã bị lỗi thời, mặc dù ban đầu chúng rất tốt. Đây là lý do của câu trả lời của tôi.
hynekcer

53 bit khi bạn bao gồm "bit ẩn", ẩn 1, ngoại trừ trong "dòng chảy dần dần".
Rick James

Đó không phải là lỗi của vòng, đó là lỗi hiển thị.
Rick James

Vâng, nó được biết đến. Tuy nhiên, tôi bỏ lỡ một bối cảnh nếu bạn phản đối một cái gì đó trong Python 2.7 Phát hành ghi chú hoặc trong văn bản của tôi hoặc không có gì cả. Nó phức tạp hơn mục đích của câu hỏi này. Cũng cần nói thêm rằng cũng chuyển đổi từ chuỗi phao đã được cố định bằng Python 2.7 do làm tròn số lỗi trên chip nhất định 32-bit Intel và rằng "Vòng () chức năng cũng là hiện nay một cách chính xác tròn." ( Ghi chú phát hành - 3.1 tính năng được nhập vào 2.7 ). Bạn có thể đồng ý không
hynekcer

1
Rất tiếc, đó là a*bvs b*a. Cảm ơn các liên kết - Nỗi nhớ.
Rick James

52

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 được ưu tiên .

Để biết thêm thông tin về tùy chọn hai, tôi đề nghị liên kết này về đị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 .

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


Làm thế nào để bạn đại diện cho một số nguyên? Nếu tôi sử dụng "{i3}". Format (numvar) tôi sẽ gặp lỗi.
skytux

Ý tôi là: Nếu numvar=12.456, sau đó "{:.2f}".format(numvar)mang lại 12.46nhưng "{:2i}".format(numvar)có lỗi và tôi đang mong đợi 12.
skytux

50

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

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

47

Không ai ở đây dường như đã đề cập đến nó, vì vậy hãy để tôi đưa ra một ví dụ ở định dạng chuỗi f / chuỗi / mẫu của Python 3.6, mà tôi nghĩ là rất gọn gàng:

>>> f'{a:.2f}'

Nó cũng hoạt động tốt với các ví dụ dài hơn, với các toán tử và không cần parens:

>>> print(f'Completed in {time.time() - start:.2f}s')

39

Bạn có thể sử dụng toán tử định dạng để làm tròn giá trị lên tới 2 vị trí thập phân trong python:

print(format(14.4499923, '.2f')) // output is 14.45

4
Chuỗi trả về này
Jemshit Iskenderov 22/03/19

29

Trong Python 2.7:

a = 13.949999999999999
output = float("%0.2f"%a)
print output

1
Điều này không giúp được gì cả. outputcùng giá trị như a, vì vậy bạn cũng có thể đã viết print athay vì print outputở dòng cuối cùng.
Đánh dấu Dickinson

@MarkDickinson Bạn có thể vui lòng thử lại không. Bởi vì nó đang chạy như mong đợi trong trình biên dịch của tôi.
Shashank Singh

1
Bạn đang thiếu quan điểm của tôi. Có, mã của bạn in 13.95. Nhưng print avới giá trị cụ thể này a, trong Python 2.7, do đó, không thực sự rõ ràng điểm của bước định dạng là gì.
Đánh dấu Dickinson

@MarkDickinson Tôi đã chỉnh sửa mã. Tôi đồng ý rằng 'in a' không in cùng giá trị với "đầu ra in". Nhưng nếu bạn so sánh "a == output", kết quả sẽ là "Sai" vì bước định dạng sẽ làm tròn giá trị nổi "a" thành hai dấu thập phân.
Shashank Singh

1
Bạn đã thực sự thử a == outputmã mà bạn hiển thị? Nó mang lại Truecho tôi, và tôi nghi ngờ nó cũng làm cho bạn.
Đánh dấu Dickinson

22

Hướng dẫn Python có một phụ lục gọi là Số học dấu phẩy động: Các vấn đề và giới hạn . Đọc nó. Nó giải thích những gì đang xảy ra và tại sao Python lại làm tốt nhất. Nó thậm chí có một ví dụ phù hợp với bạn. Hãy để tôi trích dẫn một chút:

>>> 0.1
0.10000000000000001

bạn có thể bị cám dỗ sử dụng round() hàm để cắt nó trở lại một chữ số mà bạn mong đợi. Nhưng điều đó không tạo ra sự khác biệt:

>>> round(0.1, 1)
0.10000000000000001

Vấn đề là giá trị dấu phẩy động nhị phân được lưu trữ “0.1” đã là xấp xỉ nhị phân tốt nhất có thể có 1/10, do đó, cố gắng làm tròn lại một lần nữa không thể làm cho nó tốt hơn: nó đã tốt như nó đã đạt được.

Một hậu quả khác là vì 0.1 không chính xác 1/10, nên tổng cộng mười giá trị 0.1có thể không mang lại chính xác 1.0:

>>> sum = 0.0
>>> for i in range(10):
...     sum += 0.1
...
>>> sum
0.99999999999999989

Một giải pháp thay thế và giải pháp cho các vấn đề của bạn sẽ là sử dụng decimalmô-đun.


18

Như @Matt đã chỉ ra, Python 3.6 cung cấp các chuỗi f và họ cũng có thể sử dụng các tham số lồng nhau :

value = 2.34558
precision = 2
width = 4

print(f'result: {value:{width}.{precision}f}')

cái nào sẽ hiển thị result: 2.35



11

Sử dụng kết hợp đối tượng Decimal và phương thức round ().

Python 3.7.3
>>> from decimal import Decimal
>>> d1 = Decimal (13.949999999999999) # define a Decimal
>>> d1 
Decimal('13.949999999999999289457264239899814128875732421875')
>>> d2 = round(d1, 2) # round to 2 decimals
>>> d2
Decimal('13.95')

7

Để sửa điểm nổi trong các ngôn ngữ động kiểu như Python và JavaScript, tôi sử dụng kỹ thuật này

# For example:
a = 70000
b = 0.14
c = a * b

print c # Prints 980.0000000002
# Try to fix
c = int(c * 10000)/100000
print c # Prints 980

Bạn cũng có thể sử dụng Thập phân như sau:

from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
# Results in 6 precision -> Decimal('0.142857')

getcontext().prec = 28
Decimal(1) / Decimal(7)
# Results in 28 precision -> Decimal('0.1428571428571428571428571429')

1
getcontext().prec = 6chỉ hoạt động cho phạm vi của chức năng hoặc tất cả các nơi?
Julio Marins

1
Các bối cảnh là môi trường cho các hoạt động số học. Chúng chi phối độ chính xác, đặt quy tắc làm tròn, xác định tín hiệu nào được coi là ngoại lệ và giới hạn phạm vi cho số mũ. Mỗi luồng có bối cảnh hiện tại của riêng nó @JulioMarins
Siamand

7
from decimal import Decimal


def round_float(v, ndigits=2, rt_str=False):
    d = Decimal(v)
    v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
    if rt_str:
        return v_str
    return Decimal(v_str)

Các kết quả:

Python 3.6.1 (default, Dec 11 2018, 17:41:10)
>>> round_float(3.1415926)
Decimal('3.14')
>>> round_float(3.1445926)
Decimal('3.14')
>>> round_float(3.1455926)
Decimal('3.15')
>>> round_float(3.1455926, rt_str=True)
'3.15'
>>> str(round_float(3.1455926))
'3.15'

6
orig_float = 232569 / 16000.0

14,5355625

short_float = float("{:.2f}".format(orig_float)) 

14,54


5

Điều gì về một chức năng lambda như thế này:

arred = lambda x,n : x*(10**n)//1/(10**n)

Bằng cách này bạn có thể làm:

arred(3.141591657,2)

và lấy

3.14

4

Nó đơn giản như 1,2,3:

  1. sử dụng mô-đun thập phân cho số học dấu phẩy động thập phân được làm tròn chính xác nhanh:

    d = Số thập phân (10000000.0000009)

để đạt được làm tròn:

   d.quantize(Decimal('0.01'))

sẽ có kết quả với Decimal('10000000.00')

  1. làm trên DRY:
    def round_decimal(number, exponent='0.01'):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(exponent))

HOẶC LÀ

    def round_decimal(number, decimal_places=2):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(10) ** -decimal_places)
  1. nêu lên câu trả lời này :)

PS: phê bình của người khác: định dạng không làm tròn.


2

Để làm tròn số thành độ phân giải, cách tốt nhất là cách sau, có thể hoạt động với bất kỳ độ phân giải nào (0,01 cho hai số thập phân hoặc thậm chí các bước khác):

>>> import numpy as np
>>> value = 13.949999999999999
>>> resolution = 0.01
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
13.95

>>> resolution = 0.5
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
14.0

không hoạt động với tôi trên python 3.4.3 và numpy 1.9.1? >>> nhập numpy dưới dạng np >>> res = 0,01 >>> giá trị = 0,184 >>> np.round (value / res) * res 0.17999999999999999
szeitlin

1
Tìm kiếm tài liệu tôi thấy vấn đề đến từ sự numpy.roundchính xác / chính xác. Vì vậy, nó đòi hỏi phải xác định nó là int trước khi nhân với độ phân giải. Tôi đã cập nhật mã. Cảm ơn vì điều đó!
iblasi

Điều cần thiết duy nhất là chuyển đổi numpy.float64kết quả của np.round thành floathoặc đơn giản là sử dụng round(value, 2). Không có số IEEE 754 hợp lệ tồn tại trong khoảng 13.949999999999999 (= 1395 / 100.) và 3.950000000000001 (= 1395 * .01). Tại sao bạn nghĩ rằng phương pháp của bạn là tốt nhất? Giá trị ban đầu 13.949999999999999289 (= value = round (value, 2)) thậm chí còn chính xác hơn 13.95000000000000178 của bạn (được in bởi np.float96). Thêm thông tin cho numpy bây giờ được thêm vào câu trả lời của tôi rằng bạn có thể bị hạ thấp do nhầm lẫn. Đó không phải là về numpy ban đầu.
hynekcer

@hynekcer Tôi không nghĩ rằng câu trả lời của tôi là tốt nhất. Chỉ muốn thêm một ví dụ về float float giới hạn cho n số thập phân nhưng gần nhất với độ phân giải được xác định. Tôi đã kiểm tra như bạn đã nói, thay vì intbạn cũng có thể sử dụng floatcho ví dụ @szeitlin. Cảm ơn bạn đã bình luận thêm của bạn. (Xin lỗi nhưng tôi không
hạ bệ

Thêm toàn bộ phụ thuộc mới để xử lý số (gấu trúc) là "cách tốt nhất"?
Hejazzman

1

lambda x, n: int (x * 10 n + .5) / 10 n đã làm việc cho tôi trong nhiều năm bằng nhiều ngôn ngữ.


-13

Phương pháp tôi sử dụng là cắt chuỗi. Nó tương đối nhanh chóng và đơn giản.

Đầu tiên, chuyển đổi float thành một chuỗi, chọn độ dài bạn muốn.

float = str(float)[:5]

Trong một dòng trên, chúng tôi đã chuyển đổi giá trị thành một chuỗi, sau đó chỉ giữ chuỗi đó thành bốn chữ số hoặc ký tự đầu tiên (bao gồm).

Mong rằng sẽ giúp!


2
Xin vui lòng không gửi câu trả lời giống hệt nhau cho nhiều câu hỏi.
vaultah

18
WOW ... tdh ... Xin đừng bao giờ tạo ra bất kỳ phần mềm kế toán nào ... Điều gì xảy ra nếu con số xảy ra là 113,94 ?? điều này sẽ dẫn đến 113,9 ... mất 0,04 .... Ngoài ra, điều này đã có câu trả lời từ hơn 5 năm trước ....
Angry 84
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.