如何将一个数字向上取整?

781
如何在Python中将数字向上取整?
我尝试使用round(number)函数,但它会将数字向下取整。以下是一个示例:
round(2.3) = 2.0 

而不是 3,这正是我想要的。

然后我尝试了int(number + .5),但它再次将数字舍入到下一个整数!例如:

int(2.3 + .5) = 2

13
如果数字是整数,round(number + .5) 就不起作用。例如 round(3+.5) == 4,但你实际上想要的是 3。请使用其他方法来实现四舍五入功能。 - Nearoo
30个回答

1272

math.ceil(天花板)函数返回不小于x的最小整数。

对于 Python 3:

import math
print(math.ceil(4.2))

对于 Python 2:

import math
print(int(math.ceil(4.2)))

44
说明:math.ceil 返回大于或等于输入值的最小整数。此函数将输入视为浮点数(Python 没有强类型变量),并返回一个浮点数。如果你需要一个整数,可以从返回值构造一个整数,即 int(math.ceil(363)) - R. W. Sinnet
14
事实上,有人可以说Python是强类型语言。https://dev59.com/B2gu5IYBdhLWcg3wbGml#11328980 - Bernhard
3
@TheEspinosa:是的,Python 绝对是“强类型”语言,只不过许多函数会询问某些参数的类型,并根据答案执行不同的代码。 - quamrana
30
在Python 3中,math.ceil返回一个实际的整数对象,而不仅仅是具有整数值的浮点对象。 - Arthur Tacca
6
请注意浮点数精度,由于“10000000 * 0.00136 = 13600.000000000002”,所以“ceil”函数可能会出现很大的增量,“math.ceil(10000000 * 0.00136) = 13601.0”。 - ofthestreet
2
除了在古老的、不再支持的 Python 版本中,“该函数输出一个浮点数”是不正确的。在 Python 3 中,math.ceil 返回一个 int - Mark Dickinson

320

我知道这个答案是针对之前的一个问题,但如果你不想导入math模块,只想要向上取整,这个方法对我有效。

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

如果有余数,第一部分变成了4并且第二部分计算为 "True";此外,True = 1; False = 0。因此,如果没有余数,则它保持相同的整数,但如果有余数,则会加上1。


87
好的。你还可以使用//进行整数除法,因此这个表达式可以写成 21 // 5 + (21 % 5 > 0) - naught101
4
将其作为一个漂亮的函数:def round_up(number): return int(number) + (number % 1 > 0) - Bitstream
但是你需要做很多计算,对吧?我知道,你不在乎,我也不在乎,除非我真的需要。 - france1
还有一个可以用于这个的集成divmod函数:d, m = divmod(number) return int(d) + m > 0 - VMAtm

197

如果使用整数,将数字向上舍入的一种方法是利用 // 向下取整的特性:只需在负数上进行除法运算,然后取反答案即可。不需要导入模块、浮点数或条件语句。

rounded_up = -(-numerator // denominator)
例如:
>>> print(-(-101 // 5))
21

2
当您不需要执行任何数学运算时怎么办?也就是说,您只有一个数字。 - Klik
5
@Klik: 然后你可以直接除以1 ==> -( -num // 1),这样你就能得到你的答案 :-) 祝你有美好的一天!David Bau:非常好的提议! - Marco smdm
2
不错!我一直使用(num + den - 1) // den,对于正分母的int输入来说是可以的,但如果涉及到单个非整数float(无论是分子还是分母),它就会失败;这种方法看起来更神奇,但适用于intfloat。对于小的分子,它也更快(在CPython 3.7.2上),尽管奇怪的是,当只有分子足够大以至于需要基于数组的数学运算时,你的方法反而更慢;不清楚为什么,因为除法工作应该是相似的,两个一元否定应该比加法+减法更便宜。 - ShadowRanger
2
它不需要任何导入并且速度快,这正是我所寻找的。 - Ehsan Fathi

178

需要记住的有趣的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

49
Python 2.x中,int/int的结果为整数,int/float的结果为浮点数。Python 3.x中,int/int的结果可能为浮点数。 - gecco
8
通过启用“真除法”,您可以在某些Python 2.x版本上获得类似于Python 3.x行为的结果,如此处所示。 - Rob Dennis

85

您可能也会喜欢NumPy:

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

我并不是说这比数学更好,但如果你已经在其他方面使用numpy,你可以保持代码的一致性。

无论如何,这只是一个我偶然发现的细节。我经常使用numpy,所以很惊讶它没有被提到,但当然被接受的答案完全可以胜任。


5
使用numpy也很好。最简单的方法是使用math,因为它已经是Python内置库中的一部分。这更有意义。但如果您像您提到的那样在其他问题中经常使用numpy,那么使用numpy.ceil是有意义且保持一致的 :-) 这是一个不错的提示! - Marco smdm
如果您正在使用pandas并将整个模块导入为pd,则只需使用pd.np.ceil(2.3)。无需单独导入numpy。 - ProfessorPorcupine

40

使用 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)

2
如果使用Python 3,则输入不一定需要是浮点数:ceil() 会在内部处理 - gdvalderrama
请注意,在Python 3中,round()函数实际上会像文档中所述一样将一半四舍五入为偶数,因此第二行代码将返回(4, 4, 5, 6) - hummusw

27

我很惊讶没有人提出建议

(numerator + denominator - 1) // denominator

用于整数向上取整的除法。这曾经是C/C++/CUDA常用的方法(参见divup)。


4
只适用于静态类型语言。如果分母是浮点数,那就完蛋了。 - Bharel
2
只有当分母为正数时,这种方法才能始终有效;如果分母为负数,则需要加上 1 而不是减去它,或在执行计算之前翻转分子和分母的符号。 - ShadowRanger
3
@Bharel 显然不是真的。Python 有类型,你甚至可以检查它的值。这段代码对于整数来说将会很好地工作。值得注意的是,即使在大于2^53的整数情况下,这段代码也能够正常工作,而浮点运算可能无法产生正确的结果。 - Nolan

16

这里有一种使用取模布尔值的方法。

n = 2.3
int(n) + bool(n%1)

输出:

3

3
因为不需要导入而点赞 - irene

14

对于那些想要将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

注意: ab 必须是非负整数。


对于 int_ceil(-0.1, 1) 给出了错误的答案。当它是 -1.0 时,应该是 0.0 - wlad
@ogogmad 只有当 a 和 b 是整数时才有意义。如果您有浮点数,请使用像顶部答案建议的 math.ceil。 - Pavel
int_ceil(2,-1) 对我来说返回 0。因此整数必须是非负的。 - wlad
@ogogmad 我同意,已经在答案中添加了注释,谢谢。 - Pavel
@Pavel b 是正数不就足够了吗? - user313032

13

虽然语法可能不像人们所希望的那样pythonic,但它是一个功能强大的库。

https://docs.python.org/2/library/decimal.html

from decimal import *
print(int(Decimal(2.3).quantize(Decimal('1.'), rounding=ROUND_UP)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接