Ответ 1
На самом деле вы все равно можете использовать круглую функцию:
>>> print round(1123.456789, -1)
1120.0
Это будет округлено до ближайшего кратного 10. Для 100 будет -2 в качестве второго аргумента и т.д.
Я пытаюсь округлить целые числа в python. Я посмотрел на встроенную функцию round(), но кажется, что эти раунды плавают.
Моя цель - округлить целые числа до ближайшего кратного 10. i.e.: 5- > 10, 4- > 0, 95- > 100 и т.д.
5 и выше должны округлить, 4 и ниже округлить вниз.
Это код, который у меня есть:
def round_int(x):
last_dig = int(str(x)[-1])
if last_dig >= 5:
x += 10
return (x/10) * 10
Это лучший способ достичь того, чего я хочу достичь? Есть ли встроенная функция, которая делает это? Кроме того, если это лучший способ, есть ли что-то неправильное в коде, который я пропустил при тестировании?
На самом деле вы все равно можете использовать круглую функцию:
>>> print round(1123.456789, -1)
1120.0
Это будет округлено до ближайшего кратного 10. Для 100 будет -2 в качестве второго аргумента и т.д.
round() может принимать ints и отрицательные числа для мест, которые расположены слева от десятичной дроби. Возвращаемое значение по-прежнему является поплавком, но простые исправления, которые:
>>> int(round(5678,-1))
5680
>>> int(round(5678,-2))
5700
>>> int(round(5678,-3))
6000
Немного проще:
def round_int(x):
return 10 * ((x + 5) // 10)
round(..)
, возвращающей floatЭтот float (double-precision в Python) всегда является идеальным представлением целого числа, если он находится в диапазоне [-2 53.. 2 53 ]. (Педанты обращают внимание: это не два дополнения в двойниках, поэтому диапазон симметричен относительно нуля.)
Подробнее см. здесь.
если вам нужна алгебраическая форма и по-прежнему использовать раунд, трудно получить ее проще:
interval = 5
n = 4
print(round(n/interval))*interval
Эта функция будет округляться либо на порядок (справа налево), либо цифрами так же, как формат обрабатывает десятичные знаки с плавающей запятой (слева направо:
def intround(n, p):
''' rounds an intger. if "p"<0, p is a exponent of 10; if p>0, left to right digits '''
if p==0: return n
if p>0:
ln=len(str(n))
p=p-ln+1 if n<0 else p-ln
return (n + 5 * 10**(-p-1)) // 10**-p * 10**-p
>>> tgt=5555555
>>> d=2
>>> print('\t{} rounded to {} places:\n\t{} right to left \n\t{} left to right'.format(
tgt,d,intround(tgt,-d), intround(tgt,d)))
Печать
5555555 rounded to 2 places:
5555600 right to left
5600000 left to right
Вы также можете использовать десятичный класс:
import decimal
import sys
def ri(i, prec=6):
ic=long if sys.version_info.major<3 else int
with decimal.localcontext() as lct:
if prec>0:
lct.prec=prec
else:
lct.prec=len(str(decimal.Decimal(i)))+prec
n=ic(decimal.Decimal(i)+decimal.Decimal('0'))
return n
На Python 3 вы можете надежно использовать раунд с отрицательными местами и получить округленное целое число:
def intround2(n, p):
''' will fail with larger floating point numbers on Py2 and require a cast to an int '''
if p>0:
return round(n, p-len(str(n))+1)
else:
return round(n, p)
В Python 2 раунд не сможет возвратить правильное целое число на большие числа, потому что round всегда возвращает float:
>>> round(2**34, -5)
17179900000.0 # OK
>>> round(2**64, -5)
1.84467440737096e+19 # wrong
Другие 2 функции работают на Python 2 и 3
Я хотел сделать то же самое, но с 5 вместо 10, и придумал простую функцию. Надеюсь, что это полезно:
def roundToFive(num):
remaining = num % 5
if remaining in range(0, 3):
return num - remaining
return num + (5 - remaining)