Làm tròn đến 5 (hoặc số khác) trong Python


162

Có một chức năng tích hợp có thể làm tròn như sau không?

10 -> 10
12 -> 10
13 -> 15
14 -> 15
16 -> 15
18 -> 20

Câu trả lời:


304

Tôi không biết về một hàm tiêu chuẩn trong Python, nhưng nó hoạt động với tôi:

Con trăn 2

def myround(x, base=5):
    return int(base * round(float(x)/base))

Python3

def myround(x, base=5):
    return base * round(x/base)

Thật dễ dàng để xem tại sao các công trình trên. Bạn muốn đảm bảo rằng số của bạn chia cho 5 là một số nguyên, được làm tròn chính xác. Vì vậy, trước tiên chúng tôi thực hiện chính xác điều đó ( round(float(x)/5)nơi floatchỉ cần trong Python2) và sau đó vì chúng tôi chia cho 5, chúng tôi cũng nhân với 5. Chuyển đổi cuối cùng intlà vì round()trả về giá trị dấu phẩy động trong Python 2.

Tôi đã làm cho hàm chung hơn bằng cách cho nó một basetham số, mặc định là 5.


3
Nếu chỉ có số nguyên và làm tròn xuống, thì bạn cũng có thể làmx // base * base
Tjorriemorrie

7
đây là tôi bị hoang tưởng nhưng tôi thích sử dụng floor()ceil()hơn đúc:base * floor(x/base)
user666412

1
@ user666412 math.floormath.ceilkhông cho phép sử dụng với cơ sở tùy chỉnh, vì vậy tùy chọn này không liên quan.
Acumenus

48

Để làm tròn đến các giá trị không nguyên, chẳng hạn như 0,05:

def myround(x, prec=2, base=.05):
  return round(base * round(float(x)/base),prec)

Tôi thấy điều này hữu ích vì tôi chỉ có thể thực hiện tìm kiếm và thay thế trong mã của mình để thay đổi "round (" thành "myround (", mà không phải thay đổi các giá trị tham số.


2
Bạn có thể sử dụng: def my_round(x, prec=2, base=0.05): return (base * (np.array(x) / base).round()).round(prec) cũng chấp nhận mảng numpy.
saubhik

23

Đó chỉ là vấn đề mở rộng

>>> a=[10,11,12,13,14,15,16,17,18,19,20]
>>> for b in a:
...     int(round(b/5.0)*5.0)
... 
10
10
10
15
15
15
15
15
20
20
20

14

Xóa 'phần còn lại' sẽ hoạt động:

rounded = int(val) - int(val) % 5

Nếu giá trị là một số nguyên:

rounded = val - val % 5

Là một chức năng:

def roundint(value, base=5):
    return int(value) - int(value) % int(base)

Tôi thích câu trả lời này để làm tròn đến giá trị phân số gần nhất. tức là nếu tôi chỉ muốn tăng 0,25.
áo đậu


9

round (x [, n]): các giá trị được làm tròn đến bội số gần nhất của 10 với công suất trừ n. Vì vậy, nếu n âm ...

def round5(x):
    return int(round(x*2, -1)) / 2

Vì 10 = 5 * 2, bạn có thể sử dụng phép chia và phép nhân số nguyên với 2, thay vì phép chia và phép nhân float với 5.0. Không phải là vấn đề nhiều, trừ khi bạn thích dịch chuyển bit

def round5(x):
    return int(round(x << 1, -1)) >> 1

1
+1 để cho chúng tôi thấy rằng round () có thể xử lý làm tròn thành bội số khác với 1.0, bao gồm các giá trị cao hơn. (Tuy nhiên, lưu ý rằng phương pháp thay đổi bit sẽ không hoạt động với phao, chưa kể hầu hết các lập trình viên dễ đọc hơn nhiều.)
Peter Hansen

1
@Peter Hansen cảm ơn vì +1. Cần phải có một int (x) để bit dịch chuyển hoạt động với float. Đồng ý không phải là thứ dễ đọc nhất và tôi sẽ không sử dụng nó, nhưng tôi thích "độ tinh khiết" của nó chỉ liên quan đến 1 và không phải 2 hay 5.
pwdyson

6

Xin lỗi, tôi muốn bình luận về câu trả lời của Alok Singhai, nhưng nó sẽ không cho phép tôi vì thiếu danh tiếng = /

Dù sao, chúng ta có thể khái quát thêm một bước nữa và đi:

def myround(x, base=5):
    return base * round(float(x) / base)

Điều này cho phép chúng tôi sử dụng các cơ sở không nguyên, như .25hoặc bất kỳ cơ sở phân số nào khác.


Vui lòng không cố gắng bỏ qua các hạn chế của người dùng mới bằng cách đăng nhận xét dưới dạng câu trả lời. Hạn chế tồn tại vì một lý do . Hãy xem xét điều này như một lý do có thể là Tại sao và một số câu trả lời bị xóa như thế nào?
Tạm biệt StackExchange

4

Phiên bản sửa đổi của divround :-)

def divround(value, step, barrage):
    result, rest = divmod(value, step)
    return result*step if rest < barrage else (result+1)*step

Vì vậy, trong trường hợp này bạn sử dụng divround (value, 5, 3)? hoặc có thể divround (giá trị, 5, 2.5)?
pwdyson

chính xác (giá trị, 5, 3).
Christian Hausknecht

4

Sử dụng:

>>> def round_to_nearest(n, m):
        r = n % m
        return n + m - r if r + r >= m else n - r

Nó không sử dụng phép nhân và sẽ không chuyển đổi từ / sang float.

Làm tròn đến bội số gần nhất của 10:

>>> for n in range(-21, 30, 3): print('{:3d}  =>  {:3d}'.format(n, round_to_nearest(n, 10)))
-21  =>  -20
-18  =>  -20
-15  =>  -10
-12  =>  -10
 -9  =>  -10
 -6  =>  -10
 -3  =>    0
  0  =>    0
  3  =>    0
  6  =>   10
  9  =>   10
 12  =>   10
 15  =>   20
 18  =>   20
 21  =>   20
 24  =>   20
 27  =>   30

Như bạn có thể thấy, nó hoạt động cho cả số âm và số dương. Ties (ví dụ -15 và 15) sẽ luôn được làm tròn lên.

Một ví dụ tương tự làm tròn đến bội số gần nhất của 5, chứng tỏ rằng nó cũng hoạt động như mong đợi đối với một "cơ sở" khác:

>>> for n in range(-21, 30, 3): print('{:3d}  =>  {:3d}'.format(n, round_to_nearest(n, 5)))
-21  =>  -20
-18  =>  -20
-15  =>  -15
-12  =>  -10
 -9  =>  -10
 -6  =>   -5
 -3  =>   -5
  0  =>    0
  3  =>    5
  6  =>    5
  9  =>   10
 12  =>   10
 15  =>   15
 18  =>   20
 21  =>   20
 24  =>   25
 27  =>   25

2

Trong trường hợp ai đó cần "làm tròn tài chính" (0,5 vòng luôn tăng):

def myround(x, base=5):
    roundcontext = decimal.Context(rounding=decimal.ROUND_HALF_UP)
    decimal.setcontext(roundcontext)
    return int(base *float(decimal.Decimal(x/base).quantize(decimal.Decimal('0'))))

Theo tài liệu, các tùy chọn làm tròn khác là:

ROUND_CEILING (đối với Infinity),
ROUND_DOWN (đối với zero),
ROUND_FLOOR (về phía vô cực),
ROUND_HALF_DOWN (đến gần nhất với mối quan hệ đi về phía không),
ROUND_HALF_EVEN (đến gần nhất với các mối quan hệ sẽ nguyên thậm chí gần nhất),
ROUND_HALF_UP (đến gần nhất với mối quan hệ đi cách xa số 0) hoặc
ROUND_UP (cách xa số 0).
ROUND_05UP (cách xa 0 nếu chữ số cuối cùng sau khi làm tròn về 0 sẽ là 0 hoặc 5; ngược lại về 0)

Theo mặc định, Python sử dụng ROUND_HALF_EVEN vì nó có một số lợi thế thống kê (kết quả làm tròn không bị sai lệch).


2

Đối với số nguyên và với Python 3:

def divround_down(value, step):
    return value//step*step


def divround_up(value, step):
    return (value+step-1)//step*step

Sản xuất:

>>> [divround_down(x,5) for x in range(20)]
[0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15]
>>> [divround_up(x,5) for x in range(20)]
[0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15, 20, 20, 20, 20]


1

Bội số tiếp theo của 5

Xem xét 51 cần phải được chuyển đổi thành 55:

code here

mark = 51;
r = 100 - mark;
a = r%5;
new_mark = mark + a;

1

Đây là mã C của tôi. Nếu tôi hiểu nó một cách chính xác, nó đáng lẽ phải là một cái gì đó như thế này;

#include <stdio.h>

int main(){
int number;

printf("Enter number: \n");
scanf("%d" , &number);

if(number%5 == 0)
    printf("It is multiple of 5\n");
else{
    while(number%5 != 0)
        number++;
  printf("%d\n",number);
  }
}

và điều này cũng làm tròn đến bội số gần nhất của 5 thay vì chỉ làm tròn lên;

#include <stdio.h>

int main(){
int number;

printf("Enter number: \n");
scanf("%d" , &number);

if(number%5 == 0)
    printf("It is multiple of 5\n");
else{
    while(number%5 != 0)
        if (number%5 < 3)
            number--;
        else
        number++;
  printf("nearest multiple of 5 is: %d\n",number);
  }
}

1

Một cách khác để làm điều này (không có toán tử nhân hoặc chia rõ ràng):

def rnd(x, b=5):
    return round(x + min(-(x % b), b - (x % b), key=abs))

-3

Bạn có thể lừa lừa int()thành tròn thay vì làm tròn xuống bằng cách thêm 0.5vào số bạn chuyển đến int().


2
Điều này không thực sự trả lời câu hỏi
Uri Agassi
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.