8

一直在寻找其他答案,但我仍然不明白 python 中负数的模

例如 df 的答案

x == (x/y)*y + (x%y)

所以 (-2)%5 = -2 - (-2/5)*5 = 3 是有道理的

这不是 (-2 - (-2/5)*5) =0 还是我疯了? 具有负值的模运算 - 奇怪的事情?

python中的这个负数模相同 他从哪里得到-2?

最后,如果符号取决于股息,为什么负股息与正股息的输出不一样?

例如的输出

print([8%5,-8%5,4%5,-4%5])

[3, 2, 4, 1]
4

6 回答 6

11

在 Python 中,模数是根据两个规则计算的:

  • (a // b) * b + (a % b) == a, 和
  • a % b与 具有相同的符号b

将此与整数除法向下舍入(向 -∞ 方向)这一事实相结合,并解释了由此产生的行为。

如果你这样做-8 // 5,你得到 -1.6 向下舍入,即 -2。将其乘以 5 得到 -10;2 是您必须添加到该数字才能得到 -8 的数字。因此,-8 % 5为 2。

于 2012-04-08T14:38:56.787 回答
7

在 Python 中,a // b定义为 floor(a/b),与大多数其他语言中整数除法定义为 trunc(a/b) 不同。a % b=的解释存在相应的差异a - (a // b) * b

原因是 Python 对%运算符 (and )的定义divmod通常比其他语言更有用。例如:

def time_of_day(seconds_since_epoch):
    minutes, seconds = divmod(seconds_since_epoch, 60)
    hours, minutes = divmod(minutes, 60)
    days, hours = divmod(hours, 24)
    return '%02d:%02d:%02d' % (hours, minutes, seconds)

使用此函数,如您所料,time_of_day(12345)返回。'03:25:45'

但是纪元12345 秒是几点钟呢?使用 Python 的定义divmodtime_of_day(-12345)正确返回'20:34:15'.

如果我们重新定义divmod以使用/and的 C 定义会%怎样?

def divmod(a, b):
    q = int(a / b)   # I'm using 3.x
    r = a - b * q
    return (q, r)

现在,time_of_day(-12345)返回'-3:-25:-45',这不是一天中的有效时间。如果标准 Pythondivmod函数以这种方式实现,则必须编写特殊情况代码来处理负输入。但是对于地板式的划分,就像我的第一个例子一样,它只是工作。

于 2012-04-09T13:51:25.790 回答
3

这背后的基本原理实际上是最小残留的数学定义。Python 尊重这个定义,而在大多数其他编程语言中,模运算符实际上更像是“除法后的提醒”运算符。要计算 的最小余数-5 % 11,只需将 11 与 -5 相加,直到在 范围内得到一个正整数,[0,10]结果为 6。

于 2012-04-08T14:41:28.707 回答
0

当您除以整数 (-2/5)*5时,不会计算为 -2,就像在您习惯的代数中那样。尝试将其分解为两个步骤,首先评估括号中的部分。

  1. (-2/5) * 5 = (-1) * 5
  2. (-1) * 5 = -5

第 1 步的原因是您正在执行 int 除法,在 python 2.x 中,它返回相当于浮点除法结果的四舍五入到最接近的整数。

在 python 3 及更高版本中, 2/5 将返回一个浮点数,请参阅PEP 238

于 2012-04-08T14:38:46.807 回答
0

查看此 BetterExplained 文章并查看 @David 的评论(第 6 条)以了解其他人在谈论什么。

由于我们使用整数工作,因此我们进行 int 除法,在Python中,与C相比,它会降低答案。有关这方面的更多信息,请阅读Guido 的文章

至于你的问题:

>>> 8 % 5  #B'coz (5*1) + *3* = 8
3
>>> -8 % 5 #B'coz (5*-2) + *2* = -8
2

希望有帮助。一开始我也很困惑(现在仍然如此)!:)

于 2012-04-08T14:38:56.350 回答
0

说 -a % b 需要计算。例如。r= 11 % 10 在 11 之后找到下一个可以被 10 整除的数字,即在 11 之后将下一个数字除以得到余数 0。

在上述情况下,它的 20 除以 10 得到 0。因此,20-11 = 9 是需要添加到 11 的数字。

如果 60 个弹珠需要平均分配给 8 个人的概念,实际上除以 60/8 后得到的是 7.5,因为你不能将弹珠减半,60 之后的下一个可以被 8 完全整除的值是 64。因此 4需要添加更多的弹珠,以便每个人都能分享弹珠的乐趣。

这就是 Python 在使用模运算符除负数时的做法。

于 2018-03-14T08:28:53.350 回答