欧几里德定义说,
给定两个整数a和b,其中b≠0,存在唯一的整数q和r,使得a = bq + r且0≤r<1。 | b |,其中| b |表示b的绝对值。
根据以下观察,
>>> -3 % -2 # Ideally it should be (-2 * 2) + 1
-1
>>> -3 % 2 # this looks fine, (-2 * 2) + 1
1
>>> 2 % -3 # Ideally it should be (-3 * 0) + 2
-1
看起来%
运算符正在运行不同的规则。
我的问题:
我如何理解python中模运算符的行为?我不知道有关%
运营商工作的任何其他语言。
答案 0 :(得分:4)
整数除法和模运算的行为在The History of Python的文章中解释,即:Why Python's Integer Division Floors 。我将引用相关部分:
如果其中一个操作数为负数,则结果为无效,即 圆形远离零(朝向负无穷大):
>>> -5//2 -3 >>> 5//-2 -3
这扰乱了一些人,但有一个很好的数学原因。 整数除法运算(
//
)及其兄弟,模数 操作(%
),走到一起,满足一个很好的数学 关系(所有变量都是整数):
a/b = q
,其余为r
这样
b*q + r = a
和0 <= r < b
(假设
a
和b
为>= 0
)。如果您希望关系延伸为否定
a
(保持b
积极的),你有两个选择:如果你将q
截断为零,r
将变为负数,以便将不变量更改为0 <= abs(r)
否则,你可以将q
置于负无穷大,并且 不变的遗体0 <= r < b
。在数学数论中,数学家总是喜欢后者 选择(参见例如维基百科)。对于Python,我做了同样的选择 因为模数有一些有趣的应用 操作,其中a的标志是无趣的。 [...] 对于负面b,顺便说一句,一切都只是翻转,而且是不变的 变为:
0 >= r > b.
换句话说,python决定在某些情况下打破欧几里德定义,以便在有趣的案例中获得更好的行为 。特别是负面a
被认为是有趣的,而负面b
不是被认为是有意义的。 这是完全随意的选择,不会在语言之间共享。
请注意,许多常见的编程语言(C,C ++,Java,...)不满足欧几里德不变量,通常在更多情况下而不是python(例如甚至当b
为正时)。
其中一些甚至不对剩余部分的符号提供任何保证,将该细节留作实施定义。
作为旁注:Haskell提供两种类型的模块和分区。标准欧氏模数和除法称为rem
和quot
,而浮动除法和“蟒蛇样式”模数称为mod
和div
。