Здається, про це вже слід було запитувати сотні разів (каламбур - це весело =), але я можу знайти лише функцію округлення поплавців. Як округлити ціле число, наприклад 130 -> 200
:?
Здається, про це вже слід було запитувати сотні разів (каламбур - це весело =), але я можу знайти лише функцію округлення поплавців. Як округлити ціле число, наприклад 130 -> 200
:?
Відповіді:
Округлення зазвичай виконується на числах із плаваючою комою, і тут є три основні функції, які ви повинні знати: 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–199 до 200, наприклад, округлити до найближчої сотні, то вбудована round
функція може зробити це за вас:
>>> int(round(130, -2))
100
>>> int(round(170, -2))
200
math.ceil
Канонічний спосіб зробити це - ділення і множення на 100 канонічний спосіб зробити round
, ceil
і floor
працювати на сотні.
float
порівняно з long
(звичайно!), Але для більшості практичних ситуацій a float
є досить великою.
Це пізня відповідь, але існує просте рішення, яке поєднує в собі найкращі аспекти існуючих відповідей: наступне кратне 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
є плаваючою точкою (як відповідь Мартіна Гейслера).
>>> x = 0.1
>>> x -= x % -100
>>> x
100.0
Спробуйте це:
int(round(130 + 49, -2))
Ось загальний спосіб округлення до найближчого кратного будь-якого додатного цілого числа:
def roundUpToMultiple(number, multiple):
num = number + (multiple - 1)
return num - (num % multiple)
Зразок використання:
>>> roundUpToMultiple (101, 100) 200 >>> roundUpToMultiple (654, 321) 963
lambda number, multiple: multiple * (1 + (number - 1) // multiple)
Для 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) не можуть бути точно представлені як a 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
I know the OP was about rounding an integer
- але я хотів зазначити, що ви спробуєте використати ці 3 варіанти на (0,5,10), які я очікував би повернути 10, тоді перші два методи (geisler & orozco) повернули 10, як очікувалося, тоді як
Якщо ваш int x: x + 100 - x % 100
Однак, як зазначено в коментарях, це поверне 200, якщо x==100
.
Якщо це не очікувана поведінка, ви можете використовувати x + 100*(x%100>0) - x%100
bool
має числове значення, так що так, ви можете помножити на логічний вираз. Але інші рішення є більш зрозумілими.
Спробуйте це:
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
Попередження: Попереду передчасна оптимізація ...
Оскільки так багато відповідей тут роблять час цього, я хотів додати ще одну альтернативу.
Беручи @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, було б дуже вітається.
Ось дуже просте рішення:
next_hundred = x//100*100+100
Як це працює?
Кілька прикладів
Трохи модифікований підхід раундів 1 ... 100-100, 101 ... 200-200, тощо:
next_hundred = (x-1)//100*100+100