模数运算是如何工作的?为什么Python中的模数运算与大多数语言不同?

7
下面是C++中的一些代码。如果你在Python中尝试类似-2%5的东西,结果是正3,而许多其他语言如C++、C#(代码)和Flash则给出-2。
它们为什么会给出-2,哪个版本更正确?
#include <cstdio>
int main(){
printf("%d\n", 2%5);
printf("%d\n", -2%5);
printf("%d\n", -2%77);
printf("%d\n", 2%-77);
printf("%d\n", -2%-77);
}

输出:

2
-2
-2
2
-2
3个回答

7
如果使用r = a%n,那么a = n * q + r对于某些q成立。这意味着您有许多选择r的值,具体取决于所选择的q的值。
我建议阅读http://en.wikipedia.org/wiki/Modulo_operation,该页面说明了大多数编程语言如何选择r,通常情况下r 的值在-n < r < n之间。这意味着,除非r为零,否则您有两个选择r的值 - 一个正数,一个负数。不同的编程语言对于是选择正数还是负数做出不同的决策。您会在该页面上找到总结不同语言所做决策的表:
  • Python选择与n相同符号的r(就像上面所看到的)。
  • C++ 2011选择与a相同符号的r(在2011年标准之前,它是实现定义的)。
如果想要确保在Python中获得正数,则可以使用以下代码:
r = a % n
if r < 0:
  r += n

2
根据C++ 文档

对于负值,结果可能会因库的实现而异。

这似乎很奇怪。Python 文档 只说了这个:

模运算符始终生成与其第二个操作数(或零)具有相同符号的结果;结果的绝对值严格小于第二个操作数的绝对值。

在我看来,Python 的方式更合理,但这只是我的直觉。

1
在C++98(和C-90)中,它是实现定义的。在C++11(和C-99)中,它是明确定义的:模运算符的结果符号与被除数相同。在Python中,结果的符号与除数相同。如何解释这些内容有点随意。对我来说最有意义的是提供两种实现的语言,这样作为程序员的我可以选择在某个特定上下文中更有意义的那个。 - David Hammen

-1

我想你应该看一下以下内容。除了使用略有不同的算法外,运算符优先级也很重要。试试用括号:

In [170]: 2%5
Out[170]: 2

In [171]: -2%5
Out[171]: 3

In [172]: (-2)%5
Out[172]: 3

In [173]: -(2%5)
Out[173]: -2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接