【发布时间】:2013-01-24 04:43:32
【问题描述】:
Python 中的模数令人困惑。
在 Python 中,% 运算符正在计算余数:
>>> 9 % 5
4
但是:
>>> -9 % 5
1
为什么结果是1?而不是-4?
【问题讨论】:
-
这篇关于Modular arithmetic 的维基百科文章应该清除它
标签: python modulo integer-division
Python 中的模数令人困惑。
在 Python 中,% 运算符正在计算余数:
>>> 9 % 5
4
但是:
>>> -9 % 5
1
为什么结果是1?而不是-4?
【问题讨论】:
标签: python modulo integer-division
【讨论】:
-4+5 = 1,匹配符号
-10 % 5 为0,即-10除以5。
你问为什么 -9 % 5 不是 -4,答案是 1 和 -4 都可以是正确答案,这取决于 -9 除以 5 是什么。当然 -9 除以 5 是 1.8,但是这是整数除法,在 Python 3 中用 // 表示,所以我这里用 // 来说明我们说的是整数除法。
我将不使用负数来解释这一点,它更容易。
9 // 5 是 1。也就是说,你只能从 9 中减去 5 1 次,剩下的就是 4。但是如果你再从 9 中减去 5 一次,那么剩下的就变成了 -1!
所以 -1 是 9 % 5 的正确答案,如果 9 // 5 是 2。
在 Python 9 // 5 是 1,因为 Python 整数除法是取整除法,即它总是四舍五入向下。如果它已经四舍五入 9 // 5 将是 2,而 9 % 5 将是 -1。
现在让我们看看使用负数的情况:-9 除以 5 现在是 -2。 因为是楼层除法,所以总是四舍五入。这意味着余数是 1。所以 -9 % 5 是 1,而不是 -4。
【讨论】:
这确实与 python 如何舍入整数除法有关。
在数学上,对于任何 int x 和 y,以下必须始终为真
x == (x // y) * y + x % y
因此,我们可以说
x % y == x - (x // y) * y
现在回想一下,python 将整数除法向负无穷大而不是向零舍入。 例如 -9 // 5 给出 -2,而不是 -1。用这个逻辑,你得到 -9 % 5 = 1
【讨论】:
这样想:
0 % 5 是 0
1 % 5 是 1
那么……如果你倒退怎么办?
-1 % 5 必须是 4
-2 % 5 必须是 3
等等。
你会看到下面这个 -9 % 5 是 1
注意:根据编程语言和 % 的实现,您可能会得到不同的结果,因为程序员对如何处理 % 中的负数存在分歧
【讨论】:
在整数中,您不能总是选择quotient * divisor == dividend 这样的商。如果product 不等于dividend,则总是要做出选择,是使其略小于dividend,还是略大于dividend。 product 与 remainder 的总和为 dividend,这就是 remainder 的含义。无论如何,股息和乘积必须接近,这意味着余数的绝对值必须小于除数的绝对值。
当divisor为正时,products随着quotients的增加而增加;当divisor 为负时,products 随着quotients 的增加而减少。在第一种情况下,产品从下面走,在第二种情况下,产品从上面走。在 Python 中,在这两种情况下,下一个quotient 仅在dividend 到达下一个可能的product 时才被采用,与产品的运行方式相同。在此之前,只有remainder 发生变化以适应下一个dividend,再次始终与股息变化方向相同,不会在零处中断。这条规则在 Python 中是通用的,它永远成立。
这不是做出此选择的原因,但它给出了会发生什么的想法(即,为什么结果是这样的,以及预期的结果)。
【讨论】: