Как вы округлите число в Python?


488

Эта проблема убивает меня. Как собрать число UP в Python?

Я попытался округлить (число), но оно округлило число вниз. Пример:

round(2.3) = 2.0 and not 3, what I would like

Я попробовал int (число + .5), но он снова округлил число вниз! Пример:

int(2.3 + .5) = 2

Затем я попытался раунд (число + .5), но он не будет работать в крайних случаях. Пример:

WAIT! THIS WORKED!

Пожалуйста, порекомендуйте.


4
round(number + .5)не работает, если число целое. round(3+.5) == 4когда ты действительно хочешь 3.
Nearoo

Ответы:


846

CEIL функция (потолок):

import math
print(math.ceil(4.2))

21
Разработка: math.ceil возвращает наименьшее целое число, которое больше или равно входному значению. Эта функция обрабатывает ввод как число с плавающей точкой (Python не имеет строго типизированных переменных), и функция возвращает число с плавающей точкой. Если вам нужно int, вы можете построить int из возвращаемого значения, то естьint(math.ceil(363))
RW Sinnet

9
@Sinnet: На самом деле можно сказать, что питон строго типизирован stackoverflow.com/a/11328980/5069869
Бернхард

1
@TheEspinosa: Да, python определенно строго типизирован, просто многие функции задают вопросы о типе некоторых параметров и выполняют различный код в зависимости от ответа.
Quamrana

12
@RWSinnet В Python 3 math.ceilвозвращает фактический целочисленный объект, а не просто плавающий объект с целочисленным значением.
Артур Такка

Позаботьтесь о точности поплавка, потому что 10000000 * 0.00136 = 13600.000000000002ceil может сильно math.ceil(10000000 * 0.00136) = 13601.0
возрасти

171

Я знаю, что это ответ на вопрос из давних времен, но если вы не хотите импортировать математику, и вы просто хотите округлить, это работает для меня.

>>> int(21 / 5)
4
>>> int(21 / 5) + (21 % 5 > 0)
5

Первая часть становится 4, а вторая часть оценивается как «True», если есть остаток, который, кроме того, True = 1; False = 0. Таким образом, если нет остатка, то оно остается тем же целым числом, но если есть остаток, оно добавляет 1.


38
Ницца. Вы также можете использовать //для целочисленного деления, так что это становится 21 // 5 + (21 % 5 > 0).
naught101

6
Это лучшее решение, если задействованы только целые числа. Нет ненужных floatс. Ницца.
Нико Шлёмер

158

Интересная проблема Python 2.x, о которой следует помнить:

>>> import math
>>> math.ceil(4500/1000)
4.0
>>> math.ceil(4500/1000.0)
5.0

Проблема в том, что при делении двух целых чисел в python получается другое целое число, и оно усекается перед вызовом потолка. Вы должны сделать одно значение плавающим (или приведенным), чтобы получить правильный результат.

В javascript точно такой же код дает другой результат:

console.log(Math.ceil(4500/1000));
5

44
В Python 2.x : int / int -> int и int / float -> float В Python 3.x : int / int может получиться float
gecco

7
Вы можете получить Python 3.x для поведения в определенных версиях Python 2.x, включив «истинное разделение», как показано здесь
Роб Деннис

110

При работе с целыми числами один из способов округления состоит в том, чтобы воспользоваться преимуществом факта округления //: просто выполните деление на отрицательное число, а затем отрицайте ответ. Не требуется импорт, с плавающей запятой или условно.

rounded_up = -(-numerator // denominator)

Например:

>>> print(-(-101 // 5))
21

1
Что делать, когда вам не нужно выполнять какие-либо математические операции? Т.е. у тебя просто один номер.
Клик

2
@Klik: тогда вы можете просто разделить на 1 ==> - (-num // 1), и вы получите ответ :-) Хорошего дня! Дэвид Бау: очень хорошее предложение!
Марко Смдм

10
Я рассчитал здесь все ответы, и это было в пять раз быстрее, чем следующий лучший (math.ceil). У @Andreas было то же самое время
мини-тент

@minitotent Это не удивительно, так как это простое целочисленное деление и пара операций за один цикл. Это ответ, который дает вам работу: понимание не только языка, но и всех уровней абстракций под ним.
Nearoo

Ницца! Я всегда использовал (num + den - 1) // den, что хорошо для intвходных данных с положительными знаменателями, но завершается неудачей, если floatзадействован хотя бы один нецелый (числитель или знаменатель); это выглядит более волшебно, но работает как для ints, так и для floats. Для небольших числителей это также быстрее (на CPython 3.7.2), хотя странно, когда только числитель достаточно большой, чтобы нужна математика на основе массива, ваш подход медленнее; Непонятно, почему это так, поскольку работа деления должна быть похожей, а два унарных отрицания должны быть дешевле, чем сложение + вычитание.
ShadowRanger

56

Вам также может понравиться NumPy:

>>> import numpy as np
>>> np.ceil(2.3)
3.0

Я не говорю, что это лучше, чем математика, но если вы уже использовали numpy для других целей, вы можете сохранить свой код согласованным.

Так или иначе, только деталь, с которой я столкнулся. Я часто использую NumPy и был удивлен, что об этом не упоминается, но, конечно, принятый ответ работает отлично.


3
Использование numpy тоже приятно. Проще всего было бы с математикой, так как она уже является частью Python, встроенного в библиотеки. Это имеет больше смысла. Вместо этого, как вы упомянули, если вы используете много numpy для других вопросов, тогда имеет смысл и последовательно использовать numpy.ceil :-) Хороший совет!
Марко Смдм

30

Используйтеmath.ceil для округления:

>>> import math
>>> math.ceil(5.4)
6.0

ПРИМЕЧАНИЕ : ввод должен быть плавающим.

Если вам нужно целое число, позвоните, intчтобы преобразовать его:

>>> int(math.ceil(5.4))
6

Кстати, используйте math.floorдля округления вниз и roundокругления до ближайшего целого числа.

>>> math.floor(4.4), math.floor(4.5), math.floor(5.4), math.floor(5.5)
(4.0, 4.0, 5.0, 5.0)
>>> round(4.4), round(4.5), round(5.4), round(5.5)
(4.0, 5.0, 5.0, 6.0)
>>> math.ceil(4.4), math.ceil(4.5), math.ceil(5.4), math.ceil(5.5)
(5.0, 5.0, 6.0, 6.0)

1
Входные данные не обязательно должны быть плавающими, если вы используете Python 3: об ceil() этом позаботятся внутренне
guival


11

Я удивлен, что никто не предложил

(numerator + denominator - 1) // denominator

для целочисленного деления с округлением в большую сторону. Раньше был обычный способ для C / C ++ / CUDA (ср. divup)


2
Актуально только для статически типизированных языков. Если знаменатель является поплавком, вы мертвы.
Барель

Это также работает только последовательно, если знаменатель положителен; если знаменатель отрицательный, вам нужно добавить 1вместо того, чтобы вычитать его, или перевернуть знаки числителя и знаменателя перед выполнением математики.
ShadowRanger

7

Будьте уверены, округленное значение должно быть плавающим

a = 8 
b = 21
print math.ceil(a / b)
>>> 0

но

print math.ceil(float(a) / b)
>>> 1.0

6

Попробуй это:

a = 211.0
print(int(a) + ((int(a) - a) != 0))

1
Умная. В ((int(a) - a) != 0)выражение возвращается 1всякий раз , когда aдолжен быть округляется. Вы можете расширить свой ответ и объяснить, как это работает.
Том Аранда

@ TomAranda Может кто-нибудь объяснить, как логическое выражение оценивает значение, пожалуйста?
Боуэн Лю

6
>>> def roundup(number):
...     return round(number+.5)
>>> roundup(2.3)
3
>>> roundup(19.00000000001)
20

Эта функция не требует модулей.


Что если ваш номер равен 3, то он будет округлен до того, 4что может или не может быть тем, что кто-то хочет
buydadip

15
Это работает только в 99% случаев. Вы не продумали это должным образом. Таких решений следует избегать любой ценой.
Nearoo

так что вместо +.5 сделать + .49999999 достаточно для меня.
FlyingZebra1

5

Приведенные выше ответы верны, однако импорт mathмодуля только для этой одной функции обычно кажется для меня излишним. К счастью, есть еще один способ сделать это:

g = 7/5
g = int(g) + (not g.is_integer())

Trueи Falseинтерпретируются как 1и 0в утверждении, включающем числа в Python. g.is_interger()в основном переводится как g.has_no_decimal()или g == int(g). Таким образом, последнее утверждение на английском языке читает round g down and add one if g has decimal.


1
И если вы чувствуете себя модно, вы можете использовать int(g) + (g % 1 > 0)вместо этого ;-)
Nearoo

from math import ceilпохоже исправляет импорт всего математического модуля :)
SH7890

@ SH7890 Боюсь, что эта линия мало чем отличается от import mathтого, что происходит за кулисами. Он просто удаляет все символы, кроме ceil.
Nearoo

5

Без импорта математики // используя базовые условия:

а) метод / класс метод

def ceil(fl): 
  return int(fl) + (1 if fl-int(fl) else 0)

def ceil(self, fl): 
  return int(fl) + (1 if fl-int(fl) else 0)

б) лямбда:

ceil = lambda fl:int(fl)+(1 if fl-int(fl) else 0)

5

Для тех, кто хочет округлить a / bи получить целое число:

Другой вариант с использованием целочисленного деления

def int_ceil(a, b):
    return (a - 1) // b + 1

>>> int_ceil(19, 5)
4
>>> int_ceil(20, 5)
4
>>> int_ceil(21, 5)
5

3

В случае, если кто-то хочет округлить до определенного десятичного знака:

import math
def round_up(n, decimals=0):
    multiplier = 10 ** decimals
    return math.ceil(n * multiplier) / multiplier

1

Я удивлен, что еще не видел этот ответ round(x + 0.4999), поэтому я собираюсь положить его. Обратите внимание, что это работает с любой версией Python. Изменения, внесенные в схему округления Python, усложнили ситуацию. Смотрите этот пост .

Без импорта я использую:

def roundUp(num):
    return round(num + 0.49)

testCases = list(x*0.1 for x in range(0, 50))

print(testCases)
for test in testCases:
    print("{:5.2f}  -> {:5.2f}".format(test, roundUp(test)))

Почему это работает

Из документов

Для встроенных типов, поддерживающих round (), значения округляются до ближайшего кратного 10 к степени минус n; если два множителя одинаково близки, округление выполняется до четного выбора

Поэтому 2.5 округляется до 2, а 3.5 округляется до 4. Если этого не произошло, то округление можно было бы сделать, прибавив 0,5, но мы хотим избежать перехода к половине. Таким образом, если вы добавите 0,4999, вы приблизитесь, но с достаточным запасом для округления до того, что вы обычно ожидаете. Конечно, это не удастся, если x + 0.4999равно [n].5000, но это маловероятно.


2
Используя 0.4999, он не сможет дать правильный результат для любого ввода между ???. 0000 и ???. 0001 (открытый интервал), а не только точно. 0001. Например, если вы попробуете это с 3.00005, вы получите результат 3 вместо ожидаемого 4. Конечно, вы можете уменьшить вероятность этого, добавив все больше и больше цифр до максимальной точности с плавающей точкой, но какова указать на это, если под рукой есть более надежные и интуитивно понятные решения, такие как использование math.ceil()?
blubberdiblub

@blubberdiblub В своем ответе я заявляю Without importing I use:. Я также упомянул, что он потерпит неудачу, если x + 0.4999равен [n].5000.
Клик

4
Да, вы заявляете в своем ответе, что ваше решение не импортируется, но я не вижу его ценности. mathМодуль и math.ceil()находится в стандартной библиотеке, поэтому везде для всех практических целей без установки дополнительных вещей. А что касается вашего упоминания о том, когда оно терпит неудачу, это неполно в вашем ответе, поскольку оно терпит неудачу в течение целого интервала, а не только для одной точки. Технически, вы можете возразить , что вы правы, как вы говорите , если и не тогда и только тогда , но это сделает впечатление на случайного читателя , что это менее вероятно , чем на самом деле.
blubberdiblub

0

Чтобы сделать это без какого-либо импорта:

>>> round_up = lambda num: int(num + 1) if int(num) != num else int(num)
>>> round_up(2.0)
2
>>> round_up(2.1)
3

0

Я знаю, что это было довольно давно, но я нашел довольно интересный ответ, так что здесь идет:

-round(-x-0.5)

Это исправляет случаи ребер и работает как для положительных, так и для отрицательных чисел и не требует импорта каких-либо функций.

ура


2
Это все еще округляется-round(-x-0.3) = x
Diblo Dk

0

когда вы используете 4500/1000 в python, результатом будет 4, потому что для python по умолчанию в качестве целочисленного значения присваивается логическое значение: 4500/1000 = 4.5 -> int (4.5) = 4, а ceil of 4, очевидно, равен 4

при использовании 4500 / 1000.0 результат будет 4.5, а ceil 4.5 -> 5

Используя javascript, вы получите 4.5 как результат 4500/1000, потому что javascript присваивает только результат как «числовой тип» и возвращает результат непосредственно как float

Удачи!!


Это верно только в Python 2.x. В Python 3 деление на единицу /всегда приводит к плавающей запятой, поэтому 4500/1000всегда 4,5.
Nearoo

0

Если вы не хотите ничего импортировать, вы всегда можете написать свою собственную простую функцию как:

def RoundUP(num): if num== int(num): return num return int(num + 1)


2
Это не работает, если число равно 2.05. У вас должно быть как минимум столько же цифр с цифрой 9, сколько у вас ввода, а у вас 0,999 ... что равно 1. Но тогда ваш угловой регистр 2 снова округляется. - Ну, я думаю, есть причина, по которой math.ceil существует.
Йоханнес Мария Франк

-1

Вы можете использовать разделение пола и добавить 1 к нему. 2.3 // 2 + 1


2
или используйте ceil()вместо того, чтобы странным образом делать обратное, а затем компенсирующее
guival

2
Это не сработает. Например:from math import ceil; assert 4 // 2 + 1 == ceil(4 / 2)
Карл Томе

-1

Я думаю, что вы путаете рабочие механизмы между int()и round().

int()всегда усекает десятичные числа, если задано плавающее число; тогда как round()в случае, 2.5когда 2и 3оба находятся на одинаковом расстоянии от 2.5, Python возвращает то, что больше от точки 0.

round(2.5) = 3
int(2.5) = 2

«округление» означает, что, например, 2.3получается 3, что не происходит ни в одном из ваших примеров.
Nearoo

-2

Моя доля

Я проверил print(-(-101 // 5)) = 21приведенный пример выше.

Теперь для округления:

101 * 19% = 19.19

Я не могу использовать, **поэтому я распространяю умножение на деление:

(-(-101 //(1/0.19))) = 20

-3

Я в основном новичок в Python, но если вы просто пытаетесь округлить вверх, а не вниз, почему бы не сделать:

round(integer) + 1

2
Это не будет работать для любого целого числа i, где 2,5 <целое число <3. Желаемое значение после округления до 3, но ваше выражение превратит его в 4.
Pranav Shukla

1
Я думаю, что вы имеете в виду round(integer + 0.5)Это то, что я часто делаю
Клик
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.