你能告诉我(-2) % 5
多少钱?
根据我的Python解释器是3,但你有一个明智的解释吗?
我读过在某些语言中,结果可能与机器有关,但我不确定。
答案 0 :(得分:16)
顺便说一下:大多数编程语言不同意Python并给出结果-2
。根据模数的解释,这是正确的。然而,最常见的数学定义表明, a 和 b 的模数是(严格为正的)其余 r 的划分。 a / b 。更准确地说,0 <= r &lt; b 根据定义。
答案 1 :(得分:13)
对负数进行模运算的结果似乎依赖于编程语言,这里是列表http://en.wikipedia.org/wiki/Modulo_operation
答案 2 :(得分:12)
您的Python解释器是正确的。 计算模量的一种(愚蠢的)方法是减去或加上模数,直到结果值介于0和(模数-1)之间。
例如为: 13 mod 5 =(13-5)mod 5 =(13-10)mod 5 = 3
或在您的情况下:-2 mod 5 =( - 2 + 5)mod 5 = 3
答案 3 :(得分:6)
与Binary arithmetic operations中的文档一样,Python确保:
整数除法和模运算符通过以下标识连接:
x == (x/y)*y + (x%y)
。整数除法和模数也与内置函数divmod()连接:divmod(x, y) == (x/y, x%y)
。
确实,
>>> divmod(-2, 5)
(-1, 3).
另一种可视化此方法一致性的方法是为一小段数字计算divmod
:
>>> for number in xrange(-10, 10):
... print divmod(number, 5)
...
(-2, 0)
(-2, 1)
(-2, 2)
(-2, 3)
(-2, 4)
(-1, 0)
(-1, 1)
(-1, 2)
(-1, 3)
(-1, 4)
(0, 0)
(0, 1)
(0, 2)
(0, 3)
(0, 4)
(1, 0)
(1, 1)
(1, 2)
(1, 3)
(1, 4)
答案 4 :(得分:4)
嗯,0%5应该是0,对吧?
-1%5应为4,因为这是下一个允许的数字反方向(即,它不能是5,因为它超出范围)。
遵循该逻辑,-2必须为3.
考虑它将如何工作的最简单方法是,在数字介于0(含)和5(不包括)之间的情况下,您可以继续添加或减去5。
我不确定机器的依赖性 - 我从未见过这样的实现,但我不能说它从未完成。
答案 5 :(得分:3)
正如其他答案中所解释的,对于具有负值的模运算有很多选择。通常,不同的语言(和不同的机器架构)会产生不同的结果。
模运算符总是产生一个与第二个操作数相同符号的结果(或零);结果的绝对值严格小于第二个操作数的绝对值。
是Python的选择。基本上定义模数,以便始终保持:
x == (x/y)*y + (x%y)
因此有意义的是(-2)%5 = -2 - (-2/5)* 5 = 3
答案 6 :(得分:0)
嗯,-2除以5将为0,余数为3.我不相信这应该是非常依赖于平台的,但我看到的是陌生的东西。
答案 7 :(得分:0)
确实是3.在modular arithmetic中,模数只是除法的余数,-2除以5的余数是3.
答案 8 :(得分:0)
结果取决于语言。 Python返回除数的符号,例如c#返回被除数的符号(即-2%5在c#中返回-2)。
答案 9 :(得分:0)
一种解释可能是使用2's complement存储负数。当python解释器尝试进行模运算时,它会转换为无符号值。因此,而不是做(-2)%5它实际上计算0xFFFF_FFFF_FFFF_FFFD%5,即3。
答案 10 :(得分:0)
注意不要在所有操作系统和体系结构上依赖C / C ++中的这种mod行为。如果我没记错的话,我试图依赖像
这样的C / C ++代码float x2 = x % n;
将x2保持在从0到n-1的范围内,但是当我在一个操作系统上编译时,负数会悄悄进入,但事情在另一个操作系统上可以正常工作。这是一个邪恶的时间调试,因为它只发生了一半的时间!
答案 11 :(得分:0)
术语“模数”和“余数”之间似乎存在共同的混淆。
在数学中,余数应始终定义与商一致,以便a / b == c rem d
然后(c * b) + d == a
。根据你如何围绕你的商,你得到不同的剩余。
但是,模数应始终给出结果0 <= r < divisor
,如果允许负整数,则结果只与舍入到负无穷除法一致。如果除法向零舍入(这是常见的),则模数和余数仅等于非负值。
某些语言(特别是C和C ++)没有定义所需的舍入/余数行为,%
是不明确的。许多人将舍入定义为零,但使用术语模数,其中余数更正确。 Python是相对不寻常的,因为它舍入到负无穷大,因此模数和余数是等价的。
Ada向零IIRC发展,但同时拥有mod
和rem
运营商。
C策略旨在允许编译器为机器选择最有效的实现,但IMO至少是错误的优化。一个好的编译器可能能够在不能出现负数的情况下使用等价进行优化(如果使用无符号类型,几乎可以肯定)。另一方面,在可能出现负数的情况下,您几乎肯定会关注细节 - 出于便携性的原因,您必须使用非常精心设计的过复杂算法和/或检查以确保您获得所需的结果,而不考虑舍入和余数行为。
换句话说,这种“优化”的收益主要是(如果不是总是)一种错觉,而在某些情况下会有非常实际的成本 - 所以这是一种错误的优化。