python上取整和下取整(22.为什么Python)

python上取整和下取整(22.为什么Python)(1)

本系列文章译自Python之父 Guido van Rossum 的系列博客“The History of Python”。这个博客系列对我们理解Python及其演变很有帮助,经Guido同意,在这里翻译推荐给大家,希望大家喜欢,也请大家多多指教!

系列地址:http://blog.kantli.com/theme/1

1

今天又有人问我,为什么 Python 中整数相除是向下取整,而不像 C语言一样靠 0 取整?

对正整数来说,两种取整方式的结果是一样的:

>>> 5//2 2

如果其中一个是负数,结果就不是向零靠近了(而向负无穷靠近):

>>> -5/2 -3 >>> 5//-2 -3

这个问题让一些人感到困扰,但其实是有数学考虑的。整除操作(//)与取模操作(%)是一个组合,共同实现一个数学关系(所有变量都是整数):

# a/b = q 余 r

'# b*q r = a,其中 0 <= r < b

当 a 为负数(b 保持正数),我们有两个选择:一个是让 q 向零取整,于是余数 r 会变成负数,即 0 <= abs(r) < b;另一个是让 q 向负无穷取整,则余数的设定保持不变。

数学家们总是倾向于后一种选择。(参考维基百科https://zh.wikipedia.org/wiki/模除)

而在 Python 中,我也选择了后一种方案,因为在实际应用中,存在一些 a 既可能为正数也可能为负数的情况。

以 POSIX 时间戳(1970年以来的秒数)为例,如果我们要获取当前的具体时间,由于每天为 24 * 3600 = 86400 秒,只需直接取模 t % 86400 就可以了。假如时间戳为负数,即在 1970 年之前,那么,为获得正确结果,就只能用向下取整,而不是向零取整。

我能想到的另一个例子是图像点位的计算。而且我很确定,还有许多其它例子。

顺便提一下,如果 b 取负数,整个等式就反过来了:0 >= r > b。


2

那么,C语言为什么采用了向零取整呢?或许是因为当时的硬件设计——在最早期的硬件中,负数的表现方式是“符号 数字”,而不是现在一般采用的补码(至少整数是如此)。

我用的第一台电脑是一台 CDC 主机,其整数和浮点数都是用补码表示的,60 个 1 表示的是负 0。

Tim Peters 曾担心我会把这个原则扩展到浮点数。他或许是对的,当 x 是一个非常小的负数时,向下取整原则会导致 x % 1.0 出现精度损失。但这个问题并不影响我让整数采取向下取整原则。


PS. 请注意,我用的符号是 // 而不是 /,这是 Python 3 中的句法,在 Python 2 中也可以使用,表示用户明确使用整除而不是除号。Python 2 中的 / 操作可能会有歧义,因为当两个参数都是整数时,它只返回整数,而当存在浮点数参数时,则返回浮点数。不过这是另一个故事了,可以参考 PEP 238。

公众号:ReadingPython

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页