为什么Python的math.ceil()和math.floor()操作返回浮点数而不是整数?


170

有人可以解释一下吗(直接来自文档 -我的重点):

math.ceil(x)以浮点数形式返回x的上限,最小数值大于或等于x。

math.floor(x)以浮点数形式返回x的下限,即小于或等于x 的最大数值。

为什么会.ceil.floor回报花车当它们被定义应该算整数?


编辑:

好吧,这有一些很好的论据来说明为什么它们应该返回浮点数,而当@jcollado指出它们实际上确实在Python 3中返回整数时,我才刚刚习惯这个想法。


1
我的猜测是这是因为x是一个浮点数,而不是整数,但是由于我不了解或使用Python,所以我会让别人更明确地回答。:)
Adam V

6
@ Adam-,但是ceil / floor操作的全部要点是将浮点数舍入为整数!
Yarin

1
当我第一次遇到它时,这也让我很生气,因为这似乎是错误的。至少,它并不难使用int(floor(n))
2011年

1
具有讽刺意味的是(由于使用了浮点数来防止溢出),由于采用了浮点数表示法,因此在64位int溢出之前,floor / ceil的返回值在低位无意义。[在32位的过去不是这样。]
Yves Daoust

Answers:


99

浮点数的范围通常超过整数的范围。通过返回浮点值,函数可以为超出可表示的整数范围的输入值返回有意义的值。

考虑:如果floor()返回整数,应该floor(1.0e30)返回什么?

现在,尽管Python的整数现在具有任意精度,但并不总是这样。标准库函数是等效C库函数的精简包装。


13
而且,即使Python整数现在具有任意精度,仍然有一些浮点数的下限和上限无法用整数表示。尝试floor(float("inf"))ceil(float("nan"))
Michael Hoffman

4
@ Michael-显然,在P3中,如果尝试这样做,您现在将获得OverflowExceptions。见jcollado的答案
Yarin

4
嗯,它应该返回一个“长”类型(又名“ bigint”),不是吗?似乎对我来说是一个显而易见的答案,但现在我觉得自己天真地有些幼稚。
koschei 2011年

3
@koschei:在Python 3.x中确实如此,请参阅jcollado的答案。
Greg Hewgill 2011年

另请参阅对另一个答案的评论,为什么即使对于范围内的数字也有意义。
ivan_pozdeev

96

正如其他答案所指出的那样,在python中,它们返回浮点数的原因可能是出于防止溢出问题的历史原因。但是,它们在python 3中返回整数。

>>> import math
>>> type(math.floor(3.1))
<class 'int'>
>>> type(math.ceil(3.1))
<class 'int'>

您可以在PEP 3141中找到更多信息。


@ jcollado-您在哪里看到它们在P3中返回整数?
Yarin

4
@Yarin我刚刚输入了上面的命令。另外,如果您尝试使用float("inf")float("nan"),则会出现OverflowError异常。
jcollado 2011年

10
为了完整起见,Python numpy.floorceil返回浮点数(<class'numpy.float64'>)
Neil G

1
@jcollado:float("inf")在Python 2.7或3中不会产生异常
endolith

1
@endolith你是对的,我已经检查过了,而且这种情况不再发生了。自2011
。– jcollado

18

您的评论明显说明了您的困惑:

ceil / floor操作的重点是将浮点数转换为整数!

ceil和floor操作的重点是将浮点数据舍入为整数值。不做类型转换。需要获取数值的用户可以在操作之后进行显式转换。

请注意,如果所有可用的都是返回整数的ceil或float运算,则不可能简单地实现舍入到整数值。您需要首先检查输入是否在可表示的整数范围内,然后调用该函数;您将需要在单独的代码路径中处理NaN和无穷大。

此外,如果要符合IEEE 754,则必须具有返回浮点数的ceil和floor版本。


斯蒂芬-我改写了我的评论-我的意思是四舍五入,而不是convert依。但这不是我困惑的根源,而是我没有意识到距离差异。
Yarin

可悲的是,我今天得票了。这是正确的答案,远胜于任何表示形式上的限制。
Marcin 2012年

13
在我多年的编程工作中,我不记得曾经遇到过我希望 floor / ceil的结果是浮点数而不是整数的情况。python3 确实返回整数的事实表明,这实际上是更有用的事情。我不赞成“……的要点”主张;似乎您是根据要执行的操作来定义要点,而不是程序员可能想要的。
ShreevatsaR

2
@ShreevatsaR我遇到过几次这种情况(但是,主要是在Python上下文之外)。我记得的时代是使用Mandelbrot集的时候。有时您需要输入一个整数值,但是随后立即对该值应用一些浮点运算(例如,将其缩放为0.5)。这样,与先将其转换为int然后立即将其转换回float相比,保持有底的float并对其执行浮点运算要高效得多。
blubberdiblub 2015年

17

因为python的数学库是对返回浮点数的C数学库的精简包装。


C数学库支持任意精度的整数吗?因为那是其他python数学函数返回的结果。
endlith 2013年


4

因为float的范围大于整数的范围-返回整数可能会溢出


7
整数不会在Python中溢出;当它们变得太大时,其整数将转换为bigints。打开一个Python解释器并输入“ 2 ** 500”,您会看到您得到了一个可以像对待int一样对待的对象。
koschei 2011年

@koschei:试图表示无穷大时,即使bigints也会溢出。
斯蒂芬·佳能

4

这是一个非常有趣的问题!因为浮点数需要一些位来存储指数(= bits_for_exponent),所以任何大于2**(float_size - bits_for_exponent)整数的浮点数始终是整数!在另一个极端与负指数的浮动会给之一10-1。这使整数范围浮点范围的讨论变得毫无意义,因为只要数字超出整数类型的范围,这些函数将简单地返回原始数字。python函数是函数的包装器,C因此这确实是C函数的不足之处,它们应该返回整数并强制程序员执行范围NaN//Inf在调用ceil / floor之前检查。

因此,逻辑上的答案是这些函数唯一有用的函数,它们将返回整数范围内的值,因此,它们返回浮点数的事实是一个错误,您非常聪明地意识到这一点!


1

也许因为其他语言也这样做,所以它是普遍接受的行为。(有充分的理由,如其他答案所示)


还是查尔斯所说的。:)
Almo
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.