我以前(天真的)假设模运算符返回除法的余数。我显然错了,因为 -2 % 5 返回 3。我原以为 5 除以 -2 零次,余数为 -2。
现在我了解了如何执行此操作的机制,但我的问题是为什么?有人可以给我一个链接来解释为什么模数和余数不是同义词,或者一个有用的情况的例子吗?
我以前(天真的)假设模运算符返回除法的余数。我显然错了,因为 -2 % 5 返回 3。我原以为 5 除以 -2 零次,余数为 -2。
现在我了解了如何执行此操作的机制,但我的问题是为什么?有人可以给我一个链接来解释为什么模数和余数不是同义词,或者一个有用的情况的例子吗?
a = n (mod m)
被定义为a = n + m*t
并且它同样适用于负数。(另一个看它的a = n (mod m)
意思(a - n)
是 是 的倍数m
)
-2 = 3 (mod 5) 因为 -2 = 3 - 5 (即 t = -1)
约定是取 a 的结果modulo m
是一个介于 0 和 m - 1(包括)之间的数字
The result is entirely correct. Modular arithmetic defines the following (I'll use "congruent" since I can't type the equal sign with three lines)
a congruent b mod c iff a-b is a multiple of c, i.e. x * c = (a-b) for some integer x.
E.g.
0 congruent 0 mod 5 (0 * 5 = 0-0)
1 congruent 1 mod 5 (0 * 5 = 1-1)
2 congruent 2 mod 5 (0 * 5 = 2-2)
3 congruent 3 mod 5 (0 * 5 = 3-3)
4 congruent 4 mod 5 (0 * 5 = 4-4)
5 congruent 0 mod 5 (1 * 5 = 5-0)
6 congruent 1 mod 5 (1 * 5 = 6-1)
...
The same can be extended to negative integers:
-1 congruent 4 mod 5 (-1 * 5 = -1-4)
-2 congruent 3 mod 5 (-1 * 5 = -2-3)
-3 congruent 2 mod 5 (-1 * 5 = -3-2)
-4 congruent 1 mod 5 (-1 * 5 = -4-1)
-5 congruent 5 mod 5 (-1 * 5 = -5-0)
-6 congruent 4 mod 5 (-2 * 5 = -6-4)
-7 congruent 3 mod 5 (-2 * 5 = -7-3)
...
As you can see, a lot of integers are congruent 3 mod 5: ..., -12, -7, -2, 3, 8, 13, ...
In mathematics, the set of these numbers is called the equivalence class induced by the equivalence relation "congruence". Our understanding of the remainder and the definition of the "mod" function are based on this equivalence class. The "remainder" or the result of a mod computation is a representative element of the equivalence class. By declaration we have chosen the smallest non-negative element (so -2 is not a valid candidate).
So when you read -2 mod 5 = x this translates to "Find the smallest non-negative x so that there exists an integer y with y * 5 = -2 - x", in concordance with the definition of congruence. The solution is y=1 and x = 3 as you can see by simply trying out other values for y.
你得到的基本保证是
(a % b) + b * (a / b) == a
对于有符号值,没有任何理由应该是模或除运算的首选结果。一些语言修复一种形式,而另一些语言则将其留给实现,以便实现可以使用硬件碰巧提供的任何方式。反过来,可能已选择硬件指令来有效地操作硬件对带符号整数的表示。
通常,在将有符号整数与除法、余数和位移运算一起使用时要非常小心。
将模数视为一个运算符,它将长度为 y 的线(以 y % x 表示)围绕 x 钉的圆圈。未完全环绕 x 的线的剩余长度是结果。
I guess it depends on whether you want your result rounded down or rounded towards 0:
2 / 5 = 0.4 = 5*0 + 2
works in both cases, whereas
-2 / 5 = -0.4 = 5*0 + -2
if you're rounding towards 0 (truncation),
-2 / 5 = -0.4 = 5*-1 + 3
if you're rounding down (floor).
Note that the result is always positive (for a positive divisor) in the second case and it would be useful, for example, when calculating an array index:
hashmapBuckets[getIntHash(obj) % hashmapBuckets.size].add(obj)
or normalizing an angle:
angle = angle % 360; //0-359
It is in fact the other case I'm having trouble finding practical examples for :)
--
Oh, and the Wikipedia page on the modulo operation has some nice graphs. Note that the remainder always has the same sign as the divisor for a floored division.