你能告诉我多少钱吗 (-2) % 5?根据我的Python解释器是3,但是你对此有一个明智的解释吗?

我读过,在某些语言中,结果可能取决于机器,但我不确定。

有帮助吗?

解决方案

顺便一提:大多数编程语言都会不同意 Python 并给出结果 -2. 。根据模数的解释,这是正确的。然而,最受认可的数学定义指出,模数 A 是(严格正的)休息 r 的划分 A / . 。更准确地说,0 <= r < 根据定义。

其他提示

对负数求模运算的结果似乎取决于编程语言,这里是一个列表 http://en.wikipedia.org/wiki/Modulo_operation

你的Python解释器是正确的。计算模数的一种(愚蠢)方法是减去或加上模数,直到结果值介于 0 和(模数 - 1)之间。

例如。:13 模 5 = (13 − 5) 模 5 = (13 − 10) 模 5 = 3

或者在你的情况下:−2 mod 5 = (−2 + 5) mod 5 = 3

就像文档中所说 二进制算术运算, ,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)

嗯,0 % 5 应该是 0,对吧?

-1 % 5 应该是 4,因为这是下一个允许的相反方向的数字(即,它不能是 5,因为它超出了范围)。

按照这个逻辑,-2 一定是 3。

思考它如何工作的最简单方法是不断加或减 5,直到数字落在 0(包含)和 5(不包含)之间。

我不确定机器依赖性 - 我从未见过这样的实现,但我不能说它从未完成过。

正如其他答案中所解释的,负值的模运算有很多选择。一般来说,不同的语言(和不同的机器架构)会给出不同的结果。

根据 Python参考手册,

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

是Python做出的选择。基本上模数的定义是这样的:

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

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

那么,-2 除以 5 将得到 0,余数为 3。我不认为这应该非常依赖于平台,但我见过更奇怪的事情。

确实是3。在 模运算, ,模数就是除法的余数,-2 除以 5 的余数是 3。

结果取决于语言。Python 返回除数的符号,例如 c# 返回被除数的符号(即-2 % 5 在 c# 中返回 -2)。

一种解释可能是负数存储使用 2的补码. 。当 python 解释器尝试执行模运算时,它会转换为无符号值。因此,它实际上不是执行 (-2) % 5,而是计算 0xFFFF_FFFF_FFFF_FFFD % 5,即 3。

请注意,不要在所有操作系统和体系结构上依赖 C/C++ 中的此 mod 行为。如果我没记错的话,我尝试依赖 C/C++ 代码,例如

float x2 = x % n;

将 x2 保持在 0 到 n-1 的范围内,但当我在一个操作系统上编译时,负数会悄悄出现,但在另一个操作系统上一切正常。这使得调试变得很糟糕,因为它只发生了一半的时间!

术语“模”和“余数”之间似乎存在常见的混淆。

在数学中,余数应该是 总是 与商的定义一致,因此如果 a / b == c rem d 然后 (c * b) + d == a. 。根据您对商进行四舍五入的方式,您会得到不同的余数。

然而,模数应该总是给出结果 0 <= r < divisor, ,如果允许负整数,则仅与舍入到负无穷除法一致。如果除法向零舍入(这是常见的),则模和余数仅对于非负值等效。

某些语言(特别是 C 和 C++)没有定义所需的舍入/余数行为,并且 % 是模棱两可的。许多人将舍入定义为朝零舍入,但使用术语“模”,其中余数会更正确。Python 相对不寻常,因为它四舍五入到负无穷大,因此模和余数是等效的。

Ada 向零 IIRC 舍入,但两者兼而有之 modrem 运营商。

C 策略的目的是允许编译器为机器选择最有效的实现,但至少在目前看来,这是一种错误的优化。一个好的编译器可能能够在不能出现负数的地方使用等价性进行优化(如果您使用无符号类型,则几乎可以肯定)。另一方面,在可能出现负数的情况下,您几乎肯定会关心细节 - 出于可移植性的原因,您必须使用非常仔细设计的过于复杂的算法和/或检查,以确保获得您想要的结果,而不管舍入和余数如何行为。

换句话说,这种“优化”的收益大部分(如果不是总是)是一种幻觉,而在某些情况下会产生非常真实的成本 - 所以这是一种错误的优化。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top