Кажется, что уже были спрошены сотни (каламбур fun =) раз, но я могу найти функцию для округления поплавков. Как объединить целое число, например: 130 -> 200
?
Python округляет целое число до следующих сотен
Ответ 1
Округление обычно выполняется с номерами с плавающей запятой, и здесь есть три основные функции, которые вы должны знать: round
(раунды до ближайшего целое число), math.floor
(всегда округляется вниз) и math.ceil
(всегда округляется).
Вы спрашиваете о целых числах и округлении до сотен, но мы все равно можем использовать math.ceil
, если ваши числа меньше 2 53. Чтобы использовать math.ceil
, мы просто делим сначала на 100, округляем и умножаем на 100:
>>> import math
>>> def roundup(x):
... return int(math.ceil(x / 100.0)) * 100
...
>>> roundup(100)
100
>>> roundup(101)
200
Разделение на 100 сначала и умножение на 100 после этого "сдвигает" два десятичных знака вправо и влево, так что math.ceil
работает на сотнях. Вы можете использовать 10**n
вместо 100, если вы хотите округлить до десятков (n = 1
), тысяч (n = 3
) и т.д.
Альтернативный способ сделать это - избежать чисел с плавающей запятой (они имеют ограниченную точность) и вместо этого использовать целые числа. Целые числа имеют произвольную точность в Python, поэтому это позволяет вам округлять числа любого размера. Правило округления прост: найдите остаток после деления на 100 и добавьте 100 минус этот остаток, если он отличен от нуля:
>>> def roundup(x):
... return x if x % 100 == 0 else x + 100 - x % 100
Это работает для чисел любого размера:
>>> roundup(100)
100
>>> roundup(130)
200
>>> roundup(1234567891234567891)
1234567891234567900L
Я сделал мини-тест двух решений:
$ python -m timeit -s 'import math' -s 'x = 130' 'int(math.ceil(x/100.0)) * 100'
1000000 loops, best of 3: 0.364 usec per loop
$ python -m timeit -s 'x = 130' 'x if x % 100 == 0 else x + 100 - x % 100'
10000000 loops, best of 3: 0.162 usec per loop
Чистое целочисленное решение быстрее в два раза по сравнению с решением math.ceil
.
Томас предложил целочисленное решение, идентичное тому, которое было мной выше, за исключением того, что он использует трюк путем умножения булевых значений. Интересно видеть, что не существует преимущества скорости написания кода таким образом:
$ python -m timeit -s 'x = 130' 'x + 100*(x%100>0) - x%100'
10000000 loops, best of 3: 0.167 usec per loop
В качестве заключительного замечания, позвольте мне также заметить, что если бы вы хотели округлить 101-149 до 100 и от 150 до 200 до 200, например, округлить до ближайшей сотни, то встроенная функция round
может сделать это для вас:
>>> int(round(130, -2))
100
>>> int(round(170, -2))
200
Ответ 2
Здесь общий способ округления до ближайшего кратного любого положительного целого:
def roundUpToMultiple(number, multiple):
num = number + (multiple - 1)
return num - (num % multiple)
Использование образца:
>>> roundUpToMultiple(101, 100) 200 >>> roundUpToMultiple(654, 321) 963
Ответ 3
Попробуйте следующее:
int(round(130 + 49, -2))
Ответ 4
Это поздний ответ, но есть простое решение, которое сочетает в себе лучшие аспекты существующих ответов: следующий кратный 100
от x
равен x - x % -100
(или, если хотите, x + (-x) % 100
).
>>> x = 130
>>> x -= x % -100 # Round x up to next multiple of 100.
>>> x
200
Это быстро и просто дает правильные результаты для любого целого числа x
(например, ответ Джона Мачина), а также дает разумные результаты (по сравнению с обычными оговорками о представлении с плавающей запятой), если x
- это float ( как ответ Мартина Гейслера).
>>> x = 0.1
>>> x -= x % -100
>>> x
100.0
Ответ 5
Для a
неотрицательных, b
положительных, оба целых числа:
>>> rup = lambda a, b: (a + b - 1) // b * b
>>> [(x, rup(x, 100)) for x in (199, 200, 201)]
[(199, 200), (200, 200), (201, 300)]
Обновить. Принимаемый в настоящее время ответ разваливается на целые числа, так что float (x)/float (y) не может быть точно представлен как float
. Смотрите этот код:
import math
def geisler(x, y): return int(math.ceil(x / float(y))) * y
def orozco(x, y): return x + y * (x % y > 0) - x % y
def machin(x, y): return (x + y - 1) // y * y
for m, n in (
(123456789123456789, 100),
(1234567891234567891, 100),
(12345678912345678912, 100),
):
print; print m, "m"; print n, "n"
for func in (geissler, orozco, machin):
print func(m, n), func.__name__
Вывод:
123456789123456789 m
100 n
123456789123456800 geisler
123456789123456800 orozco
123456789123456800 machin
1234567891234567891 m
100 n
1234567891234568000 geisler <<<=== wrong
1234567891234567900 orozco
1234567891234567900 machin
12345678912345678912 m
100 n
12345678912345680000 geisler <<<=== wrong
12345678912345679000 orozco
12345678912345679000 machin
И вот некоторые тайминги:
>\python27\python -m timeit -s "import math;x =130" "int(math.ceil(x/100.0))*100"
1000000 loops, best of 3: 0.342 usec per loop
>\python27\python -m timeit -s "x = 130" "x + 100 * (x % 100 > 0) - x % 100"
10000000 loops, best of 3: 0.151 usec per loop
>\python27\python -m timeit -s "x = 100" "(x + 99) // 100 * 100"
10000000 loops, best of 3: 0.0903 usec per loop
Ответ 6
Если ваш int равен x: x + 100 - x % 100
Однако, как указано в комментариях, это вернет 200, если x==100
.
Если это не ожидаемое поведение, вы можете использовать x + 100*(x%100>0) - x%100
Ответ 7
Попробуйте следующее:
import math
def ceilm(number,multiple):
'''Returns a float rounded up by a factor of the multiple specified'''
return math.ceil(float(number)/multiple)*multiple
Использование образца:
>>> ceilm(257,5)
260
>>> ceilm(260,5)
260
Ответ 8
Предупреждение: преждевременные оптимизации впереди...
Так как многие из ответов здесь соответствуют срокам этого, я хотел бы добавить еще одну альтернативу.
Принимая @Martin Geisler
def roundup(x):
return x if x % 100 == 0 else x + 100 - x % 100
(что мне больше всего нравится по нескольким причинам)
но факторизуя действие%
def roundup2(x):
x100= x % 100
return x if x100 == 0 else x + 100 - x100
Ускоряет улучшение скорости на 20% по сравнению с оригинальным
def roundup3(x):
x100 = x % 100
return x if not x100 else x + 100 - x100
Еще лучше и на 36% быстрее, чем оригинал
Наконец, я думал, что могу отказаться от оператора not
и изменить порядок веток, надеясь, что это также увеличит скорость, но было озадачено, обнаружив, что на самом деле он медленнее падает на 23% быстрее, чем оригинал.
def roundup4(x):
x100 = x % 100
return x + 100 - x100 if x100 else x
>python -m timeit -s "x = 130" "x if x % 100 == 0 else x + 100 - x % 100"
1000000 loops, best of 3: 0.359 usec per loop
>python -m timeit -s "x = 130" "x100 = x % 100" "x if x100 == 0 else x + 100 - x100"
1000000 loops, best of 3: 0.287 usec per loop
>python -m timeit -s "x = 130" "x100 = x % 100" "x if not x100 else x + 100 - x100"
1000000 loops, best of 3: 0.23 usec per loop
>python -m timeit -s "x = 130" "x100 = x % 100" "x + 100 - x100 if x100 else x"
1000000 loops, best of 3: 0.277 usec per loop
объяснения относительно того, почему 3 быстрее, а 4 будет наиболее желанным.