最近在使用python,python对带有负数的除法和取模运算让我栽了一个跟头,如 -1/2 在python中结果为-1,但是直观上看这个结果怎么也不对,应该是0才对,这个表达式的结果在C和C++下面结果跟我的预期一致,是0. 非常疑惑python的这种计算方法,于是上网bing了一番,找到了相关的解释。将我的理解整理如下。
不同语言在计算和表达除法的时候有不同的策略,大致分为三种,一种是以C, C++等为代表的静态类型计算,遇到不能整除的除法运算时将多余的部分丢掉(truncate),另外一种是以Scheme为代表,自动将除法的计算结果转化为分数,不进行截断,如 (/ 2 3) 在scheme中的结果是三分之二,还有一种以haskell为代表,haskell默认不允许Int类型之间进行除法,必须将Int类型转化为Fractional类型才能够使用除法。后两种为了保留结果的精度不进行截断。
在对除法的结果进行截断的语言中,又分为两种类型,这篇文章就以C++和python来进行对比,python 2.X 也是要进行截断处理的,下面讲一下这两种处理规则。C++的规则是:Truncate toward zero,即商向0靠近,而Python的规则是:Truncate toward negative infinity,即向负无穷截断。看这两个定义不是很直观,看下面的实例。
语言/表达式 | 11 / 5 | -11 / -5 | -11 / 5 | 11 / -5 |
---|---|---|---|---|
C++ | 2 | 2 | -2 | -2 |
Python | 2 | 2 | -3 | -3 |
可以从该表格中看出,当除数和被除数的符号相同时,C++和python的结果是一样的,不容易混淆,可以简单认为,负负抵消了,两个负数相除等于其对应的绝对值相除。后两项对比,当被除数和除数中仅有其中一项是负数时,C++的结果和python不一致了,C++结果为-2,而Python结果为-3。C++的规则是不能够整除时,商向0靠近,python是向负无穷靠近,-2更靠近0,而-3更靠近负无穷,所以C++的结果是-2,python的结果是-3.
取模运算的结果是这样定义的:
a div b = q, a mod b = r
那么有a = q * b + r,推出r = a - q * b。
那么在C++中 -11 / 5 = -2 , 那么取模运算结果r = -11 - (-2 * 5) = -1.
在Python中 -11 / 5 = -3, 那么取模运算结果是r = -11 - (-3 * 5) = 4.
另外,关于取模运算,可以总结出规律如下:
1)C++中取模的结果的符号与被除数是一致的
2)Python中取模结果的符号与除数是一致的。