有没有可以像下面这样舍入的内置函数?
10 -> 10
12 -> 10
13 -> 15
14 -> 15
16 -> 15
18 -> 20
有没有可以像下面这样舍入的内置函数?
10 -> 10
12 -> 10
13 -> 15
14 -> 15
16 -> 15
18 -> 20
I don't know of a standard function in Python, but this works for me:
def myround(x, base=5):
return base * round(x/base)
It is easy to see why the above works. You want to make sure that your number divided by 5 is an integer, correctly rounded. So, we first do exactly that (round(x/5)
), and then since we divided by 5, we multiply by 5 as well.
I made the function more generic by giving it a base
parameter, defaulting to 5.
In Python 2, float(x)
would be needed to ensure that /
does floating-point division, and a final conversion to int
is needed because round()
returns a floating-point value in Python 2.
def myround(x, base=5):
return int(base * round(float(x)/base))
It's just a matter of scaling
>>> 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
Removing the 'rest' would work:
rounded = int(val) - int(val) % 5
If the value is aready an integer:
rounded = val - val % 5
As a function:
def roundint(value, base=5):
return int(value) - int(value) % int(base)
round(x[, n]): values are rounded to the closest multiple of 10 to the power minus n. So if n is negative...
def round5(x):
return int(round(x*2, -1)) / 2
Since 10 = 5 * 2, you can use integer division and multiplication with 2, rather than float division and multiplication with 5.0. Not that that matters much, unless you like bit shifting
def round5(x):
return int(round(x << 1, -1)) >> 1
Sorry, I wanted to comment on Alok Singhai's answer, but it won't let me due to a lack of reputation =/
Anyway, we can generalize one more step and go:
def myround(x, base=5):
return base * round(float(x) / base)
This allows us to use non-integer bases, like .25
or any other fractional base.
Use:
>>> def round_to_nearest(n, m):
r = n % m
return n + m - r if r + r >= m else n - r
It does not use multiplication and will not convert from/to floats.
Rounding to the nearest multiple of 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
As you can see, it works for both negative and positive numbers. Ties (e.g. -15 and 15) will always be rounded upwards.
A similar example that rounds to the nearest multiple of 5, demonstrating that it also behaves as expected for a different "base":
>>> 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
def round_up_to_base(x, base=10):
return x + (base - x) % base
def round_down_to_base(x, base=10):
return x - (x % base)
which gives
for base=5
:
>>> [i for i in range(20)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> [round_down_to_base(x=i, base=5) for i in range(20)]
[0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15]
>>> [round_up_to_base(x=i, base=5) for i in range(20)]
[0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15, 20, 20, 20, 20]
for base=10
:
>>> [i for i in range(20)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> [round_down_to_base(x=i, base=10) for i in range(20)]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
>>> [round_up_to_base(x=i, base=10) for i in range(20)]
[0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 20, 20, 20, 20]
tested in Python 3.7.9
Modified version of divround :-)
def divround(value, step, barrage):
result, rest = divmod(value, step)
return result*step if rest < barrage else (result+1)*step
For rounding to non-integer values, such as 0.05:
I found this useful since I could just do a search and replace in my code to change "round(" to "myround(", without having to change the parameter values.