正如其他答案所指出的那样,在Python中,它们返回浮点数,可能是为了历史原因,以防止溢出问题。然而,在Python 3中,它们返回整数。
>>> import math
>>> type(math.floor(3.1))
<class 'int'>
>>> type(math.ceil(3.1))
<class 'int'>
您可以在PEP 3141中找到更多信息。
float("inf")
或 float("nan")
,你将会得到一个 OverflowError
异常。 - jcolladonumpy.floor
和ceil
返回浮点数(<class 'numpy.float64'>)。 - Neil Gfloat("inf")
不会产生异常。 - endolith浮点数的范围通常超过整数的范围。通过返回一个浮点值,函数可以为那些超出可表示整数范围的输入值返回一个合理的值。
考虑:如果floor()
返回一个整数,那么floor(1.0e30)
应该返回什么呢?
现在,虽然Python的整数现在是任意精度的,但它并不总是这样。标准库函数只是等效C库函数的薄包装器。
floor(float("inf"))
或ceil(float("nan"))
。 - Michael Hoffmanceil/floor操作的整个意义就是将浮点数转换为整数!
ceil和floor操作的目的是将浮点数据四舍五入为整数值,而不是进行类型转换。需要获取整数值的用户可以在操作后进行显式转换。
请注意,如果你只有返回整数的ceil或floor操作,那么要实现将浮点数四舍五入为整数值是不可能如此轻松的。你需要先检查输入是否在可表示的整数范围内,然后调用函数;你需要在单独的代码路径中处理NaN和无穷大。
另外,如果你想符合IEEE 754标准,你必须有返回浮点数的ceil和floor版本。
在 Python 2.4 之前,整数无法容纳截断的实数的全部范围。
http://docs.python.org/whatsnew/2.4.html#pep-237-unifying-long-integers-and-integers
bits_for_exponent
),所以任何大于2 **(float_size-bits_for_exponent)
的浮点数将始终是整数值!在另一个极端,具有负指数的浮点数将给出1
、0
或-1
中的一个。这使得讨论整数范围与浮点数范围变得无意义,因为每当数字超出整数类型的范围时,这些函数将简单地返回原始数字。Python函数是C函数的包装器,因此这实际上是C函数的缺陷,它们应该返回一个整数并强制程序员在调用ceil/floor之前进行范围/NaN
/Inf
检查。根据维基百科关于此主题的页面,floor()作为数值数学概念可追溯至1798年。https://en.wikipedia.org/wiki/Floor_and_ceiling_functions#Notation
尽管在逻辑上它是一个类似的概念,但它从来不是计算机科学中的浮点到整数存储格式函数。
在这种情况下,floor()函数一直是浮点数计算,就像数学库中的所有(大多数)函数一样。浮点数超越了整数所能做到的事情。它们包括特殊的+inf、-inf和Nan(非数字),它们都有明确定义的方式通过浮点数数值计算进行传播。Floor()始终正确地保留诸如Nan和+inf、-inf等值在数值计算中。如果Floor返回一个int,它完全破坏了数值floor()函数的整个概念。如果要成为真正的浮点数floor()函数,math.floor(float("nan"))必须返回"nan"。
最近我看到一段Python教育视频告诉我们使用:
i = math.floor(12.34/3)
为了获得一个整数,我自嘲地笑了笑,因为那位教师显然不知道该怎么做。但在写下一些尖刻的评论之前,我进行了一些测试,震惊的发现Python中的数值算法库返回的是一个整数。更奇怪的是,我认为从除法中获得整数的明显答案,竟然是使用:
i = 12.34 // 3
在Python中更好的答案是,如果你真的需要int类型,那么你应该明确地要求int:
i = int(12.34/3)
需要记住的是,floor() 向负无穷舍入,而 int() 向零舍入,因此它们对于负数给出不同的答案。因此,如果可能存在负值,则必须使用适合应用程序所需结果的函数。
然而,Python 是一个不同的东西,有充分的理由。它试图解决与 C 不同的问题集。Python 的静态类型对于快速原型设计和开发非常有用,但当针对一种对象类型(如浮点数)进行测试的代码在传递 int 参数时以微妙且难以找到的方式失败时,它可能会导致一些非常复杂和难以找到的错误。正因为如此,Python 做出了许多有趣的选择,将最小化意外错误的需求置于其他历史规范之上。
将除法始终返回 float(或某种非 int 形式)是朝着正确方向迈出的一步。出于同样的考虑,将 // 设计为 floor(a/b) 函数而不是 "int divide" 是很合理的。
将浮点数除以零变成致命错误而不是返回float("inf")同样明智,因为在大多数Python代码中,除以零不是数值计算,而是编程错误,其中数学错误或有误差的问题。当发生这种错误时,捕获该错误对于平均Python代码更为重要,而不是传播形式为“inf”的隐藏错误,该错误会导致与实际错误相隔千里。只要语言的其余部分在需要时能够很好地将int转换为float,例如在除法或math.sqrt()中,就有逻辑将math.floor()返回一个int,因为如果稍后需要它作为float,则会正确地将其转换回float。如果程序员需要一个int,那么函数会给他们需要的东西。math.floor(a/b)和a//b应该表现出相同的方式,但它们没有,我想这只是历史原因尚未调整为一致性的问题。也许由于向后兼容性问题而太难“修复”。也许并不重要???
在Python中,如果您想编写硬核数值算法,则正确的答案是使用NumPy和SciPy,而不是内置的Python math模块。
import numpy as np
nan = np.float64(0.0) / 0.0 # gives a warning and returns float64 nan
nan = np.floor(nan) # returns float64 nan
int(floor(n))
并不太难。 - wim