我发现Python中有一些关于负数的奇怪行为:
>>> -5 % 4
3
谁能解释这是怎么回事?
我发现Python中有一些关于负数的奇怪行为:
>>> -5 % 4
3
谁能解释这是怎么回事?
..., -9, -5, -1, 3, 7, ...
math.fmod
来获得与C或Java中相同的行为。
Answers:
与C或C ++不同,Python的模运算符(%
)始终返回与分母(除数)具有相同符号的数字。您的表情产生3,因为
(-5)/ 4 = -1.25->下限(-1.25)= -2
(-5)%4 =(-2×4 + 3)%4 = 3。
之所以选择它是因为C行为,因为非负结果通常更有用。一个示例是计算工作日。如果今天是星期二(第2天),那么N天之前的星期几是什么?在Python中,我们可以使用
return (2 - N) % 7
但在C中,如果Ñ ≥3,我们得到这是一个无效的号码的负数,并且我们需要通过添加7手动修复它:
int result = (2 - N) % 7;
return result < 0 ? result + 7 : result;
(有关如何确定不同语言的结果符号,请参见http://en.wikipedia.org/wiki/Modulo_operator。)
这是Guido van Rossum的解释:
http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
从本质上讲,这样a / b = q与余数r保持关系b * q + r = a且0 <= r <b。
a
,positiveb
和Python底层。事实总是如此abs(r) < b
,他们高枕无忧r <= 0
。
没有最好的方法来处理带有负数的整数除法和mod。如果a/b
幅值相同且符号相反,那就太好了(-a)/b
。如果a % b
确实是模b会很好。由于我们确实想要a == (a/b)*b + a%b
,所以前两个是不兼容的。
保留哪个是一个难题,双方都有争论。C和C ++将整数除法取整为零(因此a/b == -((-a)/b)
),而Python显然没有。
如前所述,Python模数是其他语言约定的合理理由。
这使负数具有无缝的行为,尤其是在与//
整数除法运算符结合使用时,尤其是%
模(例如,在math。divmod中):
for n in range(-8,8):
print n, n//4, n%4
产生:
-8 -2 0
-7 -2 1
-6 -2 2
-5 -2 3
-4 -1 0
-3 -1 1
-2 -1 2
-1 -1 3
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3
%
始终输出零或正数*//
总是四舍五入为负无穷大* ...只要正确的操作数为正。另一方面11 % -10 == -9
在python中,模运算符的工作原理如下。
>>> mod = n - math.floor(n/base) * base
因此结果是(针对您的情况):
mod = -5 - floor(-1.25) * 4
mod = -5 - (-2*4)
mod = 3
而其他语言(例如C,JAVA,JavaScript)则使用截断而不是floor。
>>> mod = n - int(n/base) * base
结果是:
mod = -5 - int(-1.25) * 4
mod = -5 - (-1*4)
mod = -1
如果您需要有关python取整的更多信息,请阅读this。
还值得一提的是,python中的除法也不同于C:请考虑
>>> x = -10
>>> y = 37
在C中,您期望结果
0
python中的x / y是什么?
>>> print x/y
-1
%是模数-不是余数!尽管x%y的C产量
-10
python产量。
>>> print x%y
27
您可以像在C中一样获得两者
部门:
>>> from math import trunc
>>> d = trunc(float(x)/y)
>>> print d
0
其余的(使用上面的划分):
>>> r = x - d*y
>>> print r
-10
这种计算可能不是最快的,但它适用于x和y的任何符号组合,以达到与C中相同的结果,而且它避免了条件语句。