模运算——竞技编程
Modular arithmetic - competitive programming
我看到很多有竞争力的程序员用 ((a + b) % d + d) % d
在 C++ 中编写代码。他们为什么不直接使用 (a + b) % d
?括号内的 + d
有什么用?跟负数有关系吗?
谢谢
是的,你是对的。在 C++11 之前,余数运算符 %
对于负参数的行为留给实现,但要受到一些约束。只要该参数中的其他项总和大于或等于 -d
,并且在左侧参数中添加 d
就会有所帮助,但通常情况并非如此。 (-a / d
d
的倍数对于负 a
的情况在您的特定情况下会是一个更好的加法常量。)
是的,它与负数有关。它可以防止结果在某些条件下为负数。在这种情况下,当 b
变量为负数时, b % d
的结果也为负数。此结果永远不会大于 d
,因此向此结果添加 d
会强制结果为正数。
以下代码为Java代码,原理相同:
int a = 13;
int b = -23;
int d = 31;
int result1 = (a + b % d + d) % d;
int result2 = (a + b % d) % d;
System.out.println(result1);
System.out.println(result2);
输出如下:
21
-10
为了避免整数溢出并始终保持数字为正,我们使用模运算。
当 a 为负数时,有竞争力的程序员倾向于使用 (a+b)%b
而不是 a%b
。
a%b = (a+b)%b
(a+b)%b = a%b + b%b = a%b + 0 = a%b
喜欢 a=-2
& b=5
然后 a%b = 3
我看到很多有竞争力的程序员用 ((a + b) % d + d) % d
在 C++ 中编写代码。他们为什么不直接使用 (a + b) % d
?括号内的 + d
有什么用?跟负数有关系吗?
谢谢
是的,你是对的。在 C++11 之前,余数运算符 %
对于负参数的行为留给实现,但要受到一些约束。只要该参数中的其他项总和大于或等于 -d
,并且在左侧参数中添加 d
就会有所帮助,但通常情况并非如此。 (-a / d
d
的倍数对于负 a
的情况在您的特定情况下会是一个更好的加法常量。)
是的,它与负数有关。它可以防止结果在某些条件下为负数。在这种情况下,当 b
变量为负数时, b % d
的结果也为负数。此结果永远不会大于 d
,因此向此结果添加 d
会强制结果为正数。
以下代码为Java代码,原理相同:
int a = 13;
int b = -23;
int d = 31;
int result1 = (a + b % d + d) % d;
int result2 = (a + b % d) % d;
System.out.println(result1);
System.out.println(result2);
输出如下:
21
-10
为了避免整数溢出并始终保持数字为正,我们使用模运算。
当 a 为负数时,有竞争力的程序员倾向于使用 (a+b)%b
而不是 a%b
。
a%b = (a+b)%b
(a+b)%b = a%b + b%b = a%b + 0 = a%b
喜欢 a=-2
& b=5
然后 a%b = 3