Số làm tròn đến số nguyên gần nhất


230

Tôi đã cố gắng làm tròn số float dài như:

32.268907563;
32.268907563;
31.2396694215;
33.6206896552;
...

Không có thành công cho đến nay. Tôi đã thử math.ceil(x), math.floor(x)(mặc dù nó sẽ làm tròn lên hoặc xuống, đó không phải là thứ tôi đang tìm kiếm) và round(x)nó cũng không hoạt động (vẫn là số nổi).

Tôi có thể làm gì?

EDIT: MÃ:

for i in widthRange:
    for j in heightRange:
        r, g, b = rgb_im.getpixel((i, j))
        h, s, v = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0)
        h = h * 360
        int(round(h))
        print(h)

3
Tôi sẽ thửint(x)
The Brofigator

Điều đó sẽ không đưa ra lỗi? chữ không hợp lệ cho int () với cơ sở 10:
snh_nl

Câu trả lời:


366
int(round(x))

Sẽ làm tròn nó và thay đổi nó thành số nguyên

BIÊN TẬP:

Bạn không gán int (round (h)) cho bất kỳ biến nào. Khi bạn gọi int (round (h)), nó sẽ trả về số nguyên nhưng không làm gì khác; bạn phải thay đổi dòng đó cho:

h = int(round(h))

Để gán giá trị mới cho h

EDIT 2:

Như @plowman đã nói trong các bình luận, Python round()không hoạt động như mọi người thường mong đợi và đó là vì cách số được lưu trữ dưới dạng một biến thường không phải là cách bạn nhìn thấy trên màn hình. Có rất nhiều câu trả lời giải thích cho hành vi này:

round () dường như không được làm tròn đúng

Một cách để tránh vấn đề này là sử dụng Thập phân như được nêu trong câu trả lời này: https://stackoverflow.com/a/15398691/4345659

Để câu trả lời này hoạt động chính xác mà không cần sử dụng các thư viện bổ sung, sẽ thuận tiện khi sử dụng chức năng làm tròn tùy chỉnh. Sau rất nhiều lần sửa chữa, tôi đã đưa ra giải pháp sau đây, theo như tôi đã thử nghiệm thì tránh được tất cả các vấn đề lưu trữ. Nó dựa trên việc sử dụng biểu diễn chuỗi, thu được bằng repr()(KHÔNG str()!). Có vẻ hacky nhưng đó là cách duy nhất tôi tìm thấy để giải quyết tất cả các trường hợp. Nó hoạt động với cả Python2 và Python3.

def proper_round(num, dec=0):
    num = str(num)[:str(num).index('.')+dec+2]
    if num[-1]>='5':
        return float(num[:-2-(not dec)]+str(int(num[-2-(not dec)])+1))
    return float(num[:-1])

Các xét nghiệm:

>>> print(proper_round(1.0005,3))
1.001
>>> print(proper_round(2.0005,3))
2.001
>>> print(proper_round(3.0005,3))
3.001
>>> print(proper_round(4.0005,3))
4.001
>>> print(proper_round(5.0005,3))
5.001
>>> print(proper_round(1.005,2))
1.01
>>> print(proper_round(2.005,2))
2.01
>>> print(proper_round(3.005,2))
3.01
>>> print(proper_round(4.005,2))
4.01
>>> print(proper_round(5.005,2))
5.01
>>> print(proper_round(1.05,1))
1.1
>>> print(proper_round(2.05,1))
2.1
>>> print(proper_round(3.05,1))
3.1
>>> print(proper_round(4.05,1))
4.1
>>> print(proper_round(5.05,1))
5.1
>>> print(proper_round(1.5))
2.0
>>> print(proper_round(2.5))
3.0
>>> print(proper_round(3.5))
4.0
>>> print(proper_round(4.5))
5.0
>>> print(proper_round(5.5))
6.0
>>> 
>>> print(proper_round(1.000499999999,3))
1.0
>>> print(proper_round(2.000499999999,3))
2.0
>>> print(proper_round(3.000499999999,3))
3.0
>>> print(proper_round(4.000499999999,3))
4.0
>>> print(proper_round(5.000499999999,3))
5.0
>>> print(proper_round(1.00499999999,2))
1.0
>>> print(proper_round(2.00499999999,2))
2.0
>>> print(proper_round(3.00499999999,2))
3.0
>>> print(proper_round(4.00499999999,2))
4.0
>>> print(proper_round(5.00499999999,2))
5.0
>>> print(proper_round(1.0499999999,1))
1.0
>>> print(proper_round(2.0499999999,1))
2.0
>>> print(proper_round(3.0499999999,1))
3.0
>>> print(proper_round(4.0499999999,1))
4.0
>>> print(proper_round(5.0499999999,1))
5.0
>>> print(proper_round(1.499999999))
1.0
>>> print(proper_round(2.499999999))
2.0
>>> print(proper_round(3.499999999))
3.0
>>> print(proper_round(4.499999999))
4.0
>>> print(proper_round(5.499999999))
5.0

Cuối cùng, câu trả lời đúng sẽ là:

# Having proper_round defined as previously stated
h = int(proper_round(h))

EDIT 3:

Các xét nghiệm:

>>> proper_round(6.39764125, 2)
6.31 # should be 6.4
>>> proper_round(6.9764125, 1)
6.1  # should be 7

Gotcha ở đây là decsố thập phân -th có thể là 9 và nếu dec+1chữ số -th> = 5 thì số 9 sẽ trở thành số 0 và số 1 phải được chuyển sang dec-1chữ số -th.

Nếu chúng ta cân nhắc điều này, chúng ta sẽ nhận được:

def proper_round(num, dec=0):
    num = str(num)[:str(num).index('.')+dec+2]
    if num[-1]>='5':
      a = num[:-2-(not dec)]       # integer part
      b = int(num[-2-(not dec)])+1 # decimal part
      return float(a)+b**(-dec+1) if a and b == 10 else float(a+str(b))
    return float(num[:-1])

Trong tình huống được mô tả ở trên b = 10và phiên bản trước sẽ chỉ ghép nối abđiều đó sẽ dẫn đến kết nối 10nơi dấu 0 sẽ biến mất. Phiên bản này biến đổi bsang vị trí thập phân bên phải dựa trên dec, như một thực hiện đúng.


2
print ("4.5)", int (round (4.5))) # đã cho tôi 4 lần in ("5.5)", int (round (5.5))) # đã cho tôi 6 :, (
Komm

Nó liên quan đến phiên bản Python. Nó cho tôi 5 và 6 bằng Python 2.7.9 và, như bạn đã nói, 4 và 6 sử dụng Python 3.4.2
francisco sollima

1
Đáng lưu ý: giải pháp này không làm tròn theo cách bạn có thể mong đợi. Ví dụ: làm int(round(4.5))tròn xuống 4 trong khi làm int(round(4.500001))tròn chính xác thành 5.
cày

Nếu bạn muốn một số nguyên thì round(x)có đủ trong Python 3.6.2 (và có thể cả các phiên bản thấp hơn). Kết quả là kiểu int. Lưu ý: round(x, n)sẽ là loại float.
Elmex80s

1
Điều này không hoạt động cho 112439.50093565206. Nó cho o / p -> 11253.0. Chết tiệt .. !!!!
ajin

24

Sử dụng round(x, y). Nó sẽ làm tròn số của bạn lên đến vị trí thập phân mong muốn của bạn.

Ví dụ:

>>> round(32.268907563, 3)
32.269

20

round(value,significantDigit)là giải pháp thông thường, tuy nhiên điều này không hoạt động như người ta mong đợi từ góc độ toán học khi các giá trị tròn kết thúc 5. Nếu số 5có trong chữ số ngay sau số bạn được làm tròn, các giá trị này đôi khi chỉ được làm tròn như mong đợi (nghĩa là 8.005làm tròn đến hai chữ số thập phân cho 8.01). Đối với các giá trị nhất định do các quirks của toán học dấu phẩy động, chúng được làm tròn xuống!

I E

>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01

Kỳ dị.

Giả sử ý định của bạn là làm tròn số truyền thống để thống kê trong các ngành khoa học, đây là một trình bao bọc tiện dụng để có được roundchức năng hoạt động như mong đợi cần importthêm các công cụ như Decimal.

>>> round(0.075,2)

0.07

>>> round(0.075+10**(-2*5),2)

0.08

Aha! Vì vậy, dựa trên điều này, chúng ta có thể tạo ra một chức năng ...

def roundTraditional(val,digits):
   return round(val+10**(-len(str(val))-1), digits)

Về cơ bản, điều này thêm một giá trị được đảm bảo nhỏ hơn chữ số được đưa ra ít nhất của chuỗi bạn đang cố gắng sử dụng round. Bằng cách thêm số lượng nhỏ đó, nó bảo toàn roundhành vi của nó trong hầu hết các trường hợp, trong khi bây giờ đảm bảo nếu chữ số thấp hơn chữ số được làm tròn thì 5nó có làm tròn lên không, và nếu 4nó làm tròn xuống.

Cách tiếp cận sử dụng 10**(-len(val)-1)là có chủ ý, vì đây là số nhỏ nhất mà bạn có thể thêm vào để buộc thay đổi, đồng thời đảm bảo rằng giá trị bạn thêm không bao giờ thay đổi làm tròn ngay cả khi .thiếu số thập phân . Tôi có thể sử dụng chỉ 10**(-len(val))với một điều kiện if (val>1)để trừ đi 1nhiều hơn ... nhưng đơn giản hơn là luôn luôn trừ đi 1vì điều đó sẽ không thay đổi nhiều phạm vi số thập phân có thể áp dụng mà cách giải quyết này có thể xử lý đúng. Cách tiếp cận này sẽ thất bại nếu các giá trị của bạn đạt đến giới hạn của loại, điều này sẽ thất bại, nhưng đối với gần như toàn bộ phạm vi của các giá trị thập phân hợp lệ, nó sẽ hoạt động.

Bạn cũng có thể sử dụng thư viện thập phân để thực hiện điều này, nhưng trình bao bọc tôi đề xuất đơn giản hơn và có thể được ưa thích trong một số trường hợp.


Chỉnh sửa: Cảm ơn Blckknght đã chỉ ra rằng 5trường hợp rìa chỉ xảy ra đối với các giá trị nhất định. Ngoài ra, một phiên bản trước của câu trả lời này không đủ rõ ràng rằng hành vi làm tròn số lẻ chỉ xảy ra khi chữ số ngay lập tức kém hơn chữ số mà bạn làm tròn có5 .


Tôi không chắc tại sao bạn nghĩ số thập phân với 5chữ số cuối cùng của chúng sẽ luôn làm tròn xuống. Đó không phải là trường hợp trong một thử nghiệm nhanh chóng tôi chỉ làm với những con số như 1.5, 2.5, 3.5và vân vân và 1.05, 1.15, 1.25, 1.35làm tròn đến một nơi thập phân. Tập đầu tiên (nửa chính xác làm tròn thành số nguyên nhỏ) luôn làm tròn thành số nguyên chẵn. Tập hợp sau không làm tròn một cách nhất quán, có thể là do biểu diễn nhị phân không chính xác của một số giá trị. Các phao có biểu diễn nhị phân chính xác như 1.25tròn để có một chữ số thậm chí ít quan trọng nhất, nhưng các số khác xuất hiện tròn một cách ngẫu nhiên.
Blckknght

Thú vị ... bạn nói đúng. round(4.0005,3)cho 4.0round(1.0005,3)cho 1.0, nhưng round(2.0005,3)cho 2.001round(3.0005,3)cho 3.001. Nhưng đó chính xác là lý do tại sao giải pháp đề xuất của tôi là cần thiết ... bạn không biết những gì mong đợi từ vòng chứng khoán, trong trường hợp quan trọng này!
Jason R. Mick

Cảm ơn vì điều đó. Chức năng của bạn sẽ có ích khi vấn đề này xuất hiện.
TMWP

1
Bạn có nghĩa là có , digitskết thúc của tuyên bố trở lại? Không có ý định chơi chữ. ( ý tôi là vậy)
user3342816

Ah chính xác, thực sự đó nên có trong đó. Bắt tốt ... ngạc nhiên không ai khác nhận thấy! Sẽ cứu những người sử dụng giải pháp một số thất vọng. :-)
Jason R. Mick

15

Đối với tích cực, hãy thử

int(x + 0.5)

Để làm cho nó hoạt động cho tiêu cực quá, hãy thử

int(x + (0.5 if x > 0 else -0.5))

int()hoạt động như một chức năng sàn và do đó bạn có thể khai thác tài sản này. Đây chắc chắn là cách nhanh nhất.


4
không hoạt động cho tiêu cực>>> x=-0.999 >>> int(x), round(x), int(x+0.5) (0, -1.0, 0)
user2907934 5/11/2016

3
Nếu bạn quan tâm đến các trường hợp góc, đừng sử dụng kỹ thuật "thêm 0,5 và sàn" - có một số giá trị có thể không làm tròn theo cách bạn mong đợi! Xem stackoverflow.com/a/47302585/2732969 để lấy C ++ và stackoverflow.com/a/38744026/2732969 trả lời trong chính câu hỏi này.
Anon

Tôi cần một phương pháp nhanh, nó không phải chính xác và sẽ không có nhiều trường hợp góc và lỗi trong các trường hợp góc không quan trọng trong kịch bản của tôi. Vì vậy, đây chắc chắn là hướng đến của tôi đối với một số trường hợp đặc biệt trong đó tốc độ là ưu tiên. Đừng đề nghị cho chính xác hoặc chính xác.
Đặc vụ

11

Không phải Python chỉ làm tròn một nửa đến chẵn , theo quy định của IEEE 754 sao?

Hãy cẩn thận xác định lại hoặc sử dụng tính năng làm tròn "không chuẩn"

(Xem thêm https://stackoverflow.com/a/33019948/109839 )


2
Câu trả lời này là một chút không rõ ràng. Round half to evenhoàn toàn không được quy định bởi IEEE 754, mà thay vào đó chỉ là một trong một số tùy chọn làm tròn được mô tả bởi tiêu chuẩn . Round to nearest, ties away from zero(tức là hành vi mà hầu hết mọi người mong đợi) cũng là một tùy chọn và là mặc định trong, ví dụ, C / C ++.
điện thoại

Tôi đồng ý, từ ngữ khá khó hiểu. Những gì tôi có nghĩa là Python đang đi ngang một nửa để heven (xem bảng ở phần cuối của docs.python.org/3.7/library/... nơi roundđược giải thích) và nó được làm như vậy theo cách "nửa vòng để thậm chí" được quy định để làm việc (hoặc được mô tả) theo tiêu chuẩn.
Mapio

8

Bạn cũng có thể sử dụng numpy giả sử nếu bạn đang sử dụng python3.x đây là một ví dụ

import numpy as np
x = 2.3
print(np.rint(x))
>>> 2.0

7

Giải pháp của bạn đang gọi vòng mà không chỉ định đối số thứ hai (số vị trí thập phân)

>>> round(0.44)
0
>>> round(0.64)
1

đó là một kết quả tốt hơn nhiều

>>> int(round(0.44, 2))
0
>>> int(round(0.64, 2))
0

Từ tài liệu Python tại https://docs.python.org/3/l Library / fiances.html #round

vòng (số [, ndigits])

Trả về số được làm tròn đến độ chính xác ndigits sau dấu thập phân. Nếu ndigits bị bỏ qua hoặc là Không có, nó sẽ trả về số nguyên gần nhất cho đầu vào của nó.

Ghi chú

Hành vi của vòng () đối với phao có thể gây ngạc nhiên: ví dụ: vòng (2.675, 2) cho 2,67 thay vì 2,68 như mong đợi. Đây không phải là một 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 nổi. Xem Số học dấu phẩy động: Các vấn đề và giới hạn để biết thêm thông tin.


1

Nếu bạn cần (ví dụ) một xấp xỉ hai chữ số cho A, thì int(A*100+0.5)/100.0sẽ làm những gì bạn đang tìm kiếm.

Nếu bạn cần xấp xỉ ba chữ số nhân và chia cho 1000 và cứ thế.


1

Một số thứ như thế này cũng sẽ hoạt động

import numpy as np    

def proper_round(a):
    '''
    given any real number 'a' returns an integer closest to 'a'
    '''
    a_ceil = np.ceil(a)
    a_floor = np.floor(a)
    if np.abs(a_ceil - a) < np.abs(a_floor - a):
        return int(a_ceil)
    else:
        return int(a_floor)

0

Đối với mục đích này, tôi sẽ đề nghị chỉ làm những điều sau đây -

int(round(x))

Điều này sẽ cung cấp cho bạn số nguyên gần nhất.

Hi vọng điêu nay co ich!!


0

Tôi sử dụng và có thể tư vấn cho giải pháp sau (python3.6):

y = int(x + (x % (1 if x >= 0 else -1)))

Nó hoạt động tốt đối với một nửa số (dương và âm) và hoạt động thậm chí nhanh hơn int (vòng (x)):

round_methods = [lambda x: int(round(x)), 
                 lambda x: int(x + (x % (1 if x >= 0 else -1))),
                 lambda x: np.rint(x).astype(int),
                 lambda x: int(proper_round(x))]

for rm in round_methods:
    %timeit rm(112.5)
Out:
201 ns ± 3.96 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
159 ns ± 0.646 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
925 ns ± 7.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
1.18 µs ± 8.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

for rm in round_methods:
    print(rm(112.4), rm(112.5), rm(112.6))
    print(rm(-12.4), rm(-12.5), rm(-12.6))
    print('=' * 11)

Out:
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========
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.