在编程中,在将一个整数除以另一个整数后,取模运算给出除法的余数或有符号余数。它是编程中最常用的运算符之一。本文讨论了何时以及为什么取模运算会产生否定结果。
例子:
- 在C中, 3%2返回1 。但是, -3%2为-1,而3%-2为1 。
- 在Python, -3%2为1,而3%-2为-1 。
因此,很明显,在不同的编程语言中, -3%2的相同表达式给出不同的结果。这个结果与数学而不是编程更相关。这里提到的数学将有助于更轻松地理解问题。
要理解为什么会发生这种情况,需要对欧几里得除法有一点了解,并需要与模块化算术有关的一些知识。
欧几里德除法(Euclidean Division) :在算术中,欧几里德除法或除以除数是将一个整数(被除数)除以另一个(除数)的过程,其方式是产生商 和一个 余数小于除数。
给定两个整数a和b (其中b≠0 ),则存在唯一的整数q和r ,使得:
a = bq + r ( 0 ≤ r < |b| )
where, |b| denotes the absolute value of b.
在上式中,四个整数中的每个都有其自己的名称,即
- a称为红利。
- b称为除数。
- q称为商。
- r称为余数。
例如:
- 如果a = 9且b = 4,则q = 2且r = 1,因为9 = 4×2 +1。
- 如果a = -9和b = 4,则q = -3且r = 3,因为-9 = 4×-3 + 3。
- 如果a = 9且b = -4,则q = -2且r = 1,因为9 = -4×-2 + 1。
- 如果a = -9和b = -4,则q = 3且r = 3,因为-9 = -4×3 + 3。
以上示例的说明:
- 第一个例子不言自明,因为9/4给出商2和余数1。
- 第二个示例(-9/4)给出商-3而不是-2 。发生这种情况是因为,如果我们以-2为商,则-9 = 4×-2 +(-1) 。剩余的-1不能满足欧几里得除法的条件。它不会使-9/4 = -2错误,这不是我们在这种情况下所需要的。
模数运算:在数学中,模数运算是一种用于整数的算术系统,其中,数字在达到一定值(称为模数)时会“环绕”。
同余:给定任何整数N (称为模数),如果两个整数a和b在除以N时产生相同的余数,则称它们为N的模余。
a = pN + r and b = qN + r, where 0 ≤ r < |N| is the common remainder.
同余模N表示为a≡b(mod N)
其中括号表示(mod N)适用于整个方程,而不仅适用于右侧(在此为b )。
例子:
- -5≡2(mod 7)
- -14≡19(mod 11)
分析第一个例子。 -5 = 7×-1 + 2和2 = 7×0 + 2 。当被7除时, -5和2保留相同的余数2 。因此,它们彼此一致。
同样, -14 = 11×-2 + 8和19 = 11×1 + 8 。 -14和19在除以11时会保留相同的余数8 。因此,它们彼此一致。
同余类:假设当除以满足条件0≤r <| N |的N时,模N留下余数r 。 。与mod N相等的所有整数的集合称为整数mod N的一致性类。例如:
- 3 mod 2的全等类为{…,-5,-3,-1、1、3、5、7…}。
- 7 mod 4的全等类为{…,-9,-5,-1、3、7、11…}。
从整数N的同余类中选择任何整数作为该类的代表。在数学中,选择属于该类别的最小正残数,最小非负整数作为代表。例如:
- 同余类3 mod 2的代表是1。
- 同等类7 mod 4的代表是3。
选择最小的正残基是因为它是欧几里得分裂后产生的剩余残基。
代表由编程语言选择:
- 如果a和N均为正,则在所有编程语言中,模N是欧几里得除法的余数。但是,当a或N为负或两者均为负时,会观察到结果的差异。然后, mod N的答案取决于编程语言所使用的mod N的实现。所有编程语言产生的余数的确遵循特定标准,即| r |。 <| N | 。
- 但是,如果余数不为零,这仍然会产生符号歧义,然后会出现两种可能的余数选择:一个负数( mod N的同余类的最大负数)和另一个正数(最小正数)模N的同余类的定义。其他元素不满足| r |的条件<| N | 。
- 这就是为什么在C和Python执行-3 mod 2会有不同的结果的原因。他们两个都产生正确的结果。他们只是不输出数学上代表mod N的代表。
- 在C中, -3 mod 2返回-1 ,这是-3 mod 2的成员类。但是, Python返回1 ,它再次是-3 mod 2的成员类。同样,两个答案都返回以满足| r |的给定条件。 <| N | 。
编程语言中%的实现:诸如C , C++ , Java , JavaScript之类的许多编程语言都使用类似于以下给出的一种实现。其余部分根据等式返回
r = a – N*trunc(a/N)
下面是上述说明的实现:
C++14
// C++14 program to illustrate modulo
// operations using the above equation
#include
using namespace std;
// Function to calculate and
// return the remainder of a % n
int truncMod(int a, int n)
{
// (a / n) implicitly gives
// the truncated result
int q = a / n;
return a - n * q;
}
// Driver Code
int main()
{
int a, b;
// Modulo of two positive numbers
a = 9;
b = 4;
cout << a << " % "
<< b << " = "
<< truncMod(a, b) << endl;
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
cout << a << " % "
<< b << " = "
<< truncMod(a, b) << endl;
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
cout << a << " % "
<< b << " = "
<< truncMod(a, b) << endl;
// Modulo of two negative numbers
a = -9;
b = -4;
cout << a << " % "
<< b << " = "
<< truncMod(a, b) << endl;
}
// This code is contributed by mohit kumar 29
Java
// Java program to illustrate modulo
// operations using the above equation
class GFG {
// Function to calculate and
// return the remainder of a % n
static int truncMod(int a, int n)
{
// (a / n) implicitly gives
// the truncated result
int q = a / n;
return a - n * q;
}
// Driver Code
public static void main(String[] args)
{
int a, b;
// Modulo of two positive numbers
a = 9;
b = 4;
System.out.println(a + " % " + b + " = "
+ truncMod(a, b));
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
System.out.println(a + " % " + b + " = "
+ truncMod(a, b));
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
System.out.println(a + " % " + b + " = "
+ truncMod(a, b));
// Modulo of two negative numbers
a = -9;
b = -4;
System.out.println(a + " % " + b + " = "
+ truncMod(a, b));
}
}
Python3
# Python3 program to illustrate modulo
# operations using the above equation
# Function to calculate and
# return the remainder of a % n
def truncMod(a, n):
# (a / n) implicitly gives
# the truncated result
q = a // n
return a - n * q
# Driver Code
if __name__ == '__main__':
# Modulo of two positive numbers
a = 9
b = 4
print(a,"%",b,"=",truncMod(a, b))
# Modulo of a negative number
# by a positive number
a = -9
b = 4
print(a,"%",b,"=",truncMod(a, b))
# Modulo of a positive number
# by a negative number
a = 9
b = -4
print(a,"%",b,"=",truncMod(a, b))
# Modulo of two negative numbers
a = -9
b = -4
print(a,"%",b,"=",truncMod(a, b))
# This code is contributed by SURENDRA_GANGWAR.
C#
// C# program for the above approach
using System;
public class GFG
{
// Function to calculate and
// return the remainder of a % n
static int truncMod(int a, int n)
{
// (a / n) implicitly gives
// the truncated result
int q = a / n;
return a - n * q;
}
// Driver Code
static public void Main()
{
int a, b;
// Modulo of two positive numbers
a = 9;
b = 4;
Console.WriteLine(a + " % " + b + " = "
+ truncMod(a, b));
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
Console.WriteLine(a + " % " + b + " = "
+ truncMod(a, b));
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
Console.WriteLine(a + " % " + b + " = "
+ truncMod(a, b));
// Modulo of two negative numbers
a = -9;
b = -4;
Console.WriteLine(a + " % " + b + " = "
+ truncMod(a, b));
}
}
// This code is contributed by snjoy_62.
C++
// C++ program to illustrate modulo
// operations using the above equation
#include
using namespace std;
// Function to calculate and
// return the remainder of a % n
int floorMod(int a, int n)
{
// Type casting is necessary
// as (int) / (int) will give
// int result, i.e. -3 / 2
// will give -1 and not -1.5
int q = (int)floor((double)a / n);
// Return the resultant remainder
return a - n * q;
}
// Driver Code
int main()
{
int a, b;
// Modulo of two positive numbers
a = 9;
b = 4;
cout << a << " % " << b
<< " = " << floorMod(a, b) << "\n";
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
cout << a << " % " << b
<< " = " << floorMod(a, b) << "\n";
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
cout << a << " % " << b
<< " = " << floorMod(a, b) << "\n";
// Modulo of two negative numbers
a = -9;
b = -4;
cout << a << " % " << b
<< " = " << floorMod(a, b) << "\n";
return 0;
}
// This code is contributed by Kingash
Java
// Java program to illustrate modulo
// operations using the above equation
public class GFG {
// Function to calculate and
// return the remainder of a % n
static int floorMod(int a, int n)
{
// Type casting is necessary
// as (int) / (int) will give
// int result, i.e. -3 / 2
// will give -1 and not -1.5
int q = (int)Math.floor((double)a / n);
// Return the resultant remainder
return a - n * q;
}
// Driver Code
public static void main(String[] args)
{
int a, b;
// Modulo of two positive numbers
a = 9;
b = 4;
System.out.println(a + " % " + b + " = "
+ floorMod(a, b));
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
System.out.println(a + " % " + b + " = "
+ floorMod(a, b));
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
System.out.println(a + " % " + b + " = "
+ floorMod(a, b));
// Modulo of two negative numbers
a = -9;
b = -4;
System.out.println(a + " % " + b + " = "
+ floorMod(a, b));
}
}
C++
// C++ program for the above idea
#include
using namespace std;
// Driver Code
int main()
{
int a, b, r;
// Modulo of two positive numbers
a = 9;
b = 4;
r = a % b > 0 ? a % b : abs(b) + a % b;
cout << a << " % " << b << " = " << r << "\n";
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
r = a % b > 0 ? a % b : abs(b) + a % b;
cout << a << " % " << b << " = " << r << "\n";
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
r = a % b > 0 ? a % b : abs(b) + a % b;
cout << a << " % " << b << " = " << r << "\n";
// Modulo of two negative numbers
a = -9;
b = -4;
r = a % b > 0 ? a % b : abs(b) + a % b;
cout << a << " % " << b << " = " << r << "\n";
return 0;
}
// This code is contributed by Kingash
Java
// Java program for the above idea
public class PositiveModulus {
// Driver Code
public static void main(String args[])
{
int a, b, r;
// Modulo of two positive numbers
a = 9;
b = 4;
r = a % b > 0 ? a % b : Math.abs(b) + a % b;
System.out.println(a + " % " + b + " = " + r);
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
r = a % b > 0 ? a % b : Math.abs(b) + a % b;
System.out.println(a + " % "
+ b + " = " + r);
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
r = a % b > 0 ? a % b : Math.abs(b) + a % b;
System.out.println(a + " % "
+ b + " = " + r);
// Modulo of two negative numbers
a = -9;
b = -4;
r = a % b > 0 ? a % b : Math.abs(b) + a % b;
System.out.println(a + " % "
+ b + " = " + r);
}
}
C#
// C# program for the above idea
using System;
using System.Collections.Generic;
class GFG{
// Driver Code
public static void Main(string[] args)
{
int a, b, r;
// Modulo of two positive numbers
a = 9;
b = 4;
r = a % b > 0 ? a % b : Math.Abs(b) + a % b;
Console.WriteLine(a + " % " + b + " = " + r);
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
r = a % b > 0 ? a % b : Math.Abs(b) + a % b;
Console.WriteLine(a + " % " + b + " = " + r);
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
r = a % b > 0 ? a % b : Math.Abs(b) + a % b;
Console.WriteLine(a + " % " + b + " = " + r);
// Modulo of two negative numbers
a = -9;
b = -4;
r = a % b > 0 ? a % b : Math.Abs(b) + a % b;
Console.WriteLine(a + " % " + b + " = " + r);
}
}
// This code is contributed by avijitmondal1998
9 % 4 = 1
-9 % 4 = -1
9 % -4 = 1
-9 % -4 = -1
注意:具有上述实现方式的其他编程语言也会产生相似的结果。注意一些有趣的事情,当红利为负数时,得出的答案也将为负数,并且将是该同余类中最大的负数成员。当红利为正数时,产生的答案也将为正数,并且是同余类中最不积极的成员。
许多编程语言(例如Python , Ruby和Perl)都使用类似于以下给出的实现。其余部分根据等式返回
r = a – N × floor(a/b)
下面是上述说明的实现:
C++
// C++ program to illustrate modulo
// operations using the above equation
#include
using namespace std;
// Function to calculate and
// return the remainder of a % n
int floorMod(int a, int n)
{
// Type casting is necessary
// as (int) / (int) will give
// int result, i.e. -3 / 2
// will give -1 and not -1.5
int q = (int)floor((double)a / n);
// Return the resultant remainder
return a - n * q;
}
// Driver Code
int main()
{
int a, b;
// Modulo of two positive numbers
a = 9;
b = 4;
cout << a << " % " << b
<< " = " << floorMod(a, b) << "\n";
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
cout << a << " % " << b
<< " = " << floorMod(a, b) << "\n";
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
cout << a << " % " << b
<< " = " << floorMod(a, b) << "\n";
// Modulo of two negative numbers
a = -9;
b = -4;
cout << a << " % " << b
<< " = " << floorMod(a, b) << "\n";
return 0;
}
// This code is contributed by Kingash
Java
// Java program to illustrate modulo
// operations using the above equation
public class GFG {
// Function to calculate and
// return the remainder of a % n
static int floorMod(int a, int n)
{
// Type casting is necessary
// as (int) / (int) will give
// int result, i.e. -3 / 2
// will give -1 and not -1.5
int q = (int)Math.floor((double)a / n);
// Return the resultant remainder
return a - n * q;
}
// Driver Code
public static void main(String[] args)
{
int a, b;
// Modulo of two positive numbers
a = 9;
b = 4;
System.out.println(a + " % " + b + " = "
+ floorMod(a, b));
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
System.out.println(a + " % " + b + " = "
+ floorMod(a, b));
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
System.out.println(a + " % " + b + " = "
+ floorMod(a, b));
// Modulo of two negative numbers
a = -9;
b = -4;
System.out.println(a + " % " + b + " = "
+ floorMod(a, b));
}
}
9 % 4 = 1
-9 % 4 = 3
9 % -4 = -3
-9 % -4 = -1
注意:具有上述实现的其他编程语言也会产生相似的结果。现在,当除数为负数时,所产生的答案也将为负数,以及该同余类中最大的负数成员。当除数为正时,产生的答案也将为正,并且它将是该同余类中最不肯定的成员。
所有语言都产生正确的结果。他们只是选择该解决方案全班的不同代表。为了仅产生全等类别的最小正残数作为答案,而与所使用的实现方式无关。
下面是上述方法的实现:
C++
// C++ program for the above idea
#include
using namespace std;
// Driver Code
int main()
{
int a, b, r;
// Modulo of two positive numbers
a = 9;
b = 4;
r = a % b > 0 ? a % b : abs(b) + a % b;
cout << a << " % " << b << " = " << r << "\n";
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
r = a % b > 0 ? a % b : abs(b) + a % b;
cout << a << " % " << b << " = " << r << "\n";
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
r = a % b > 0 ? a % b : abs(b) + a % b;
cout << a << " % " << b << " = " << r << "\n";
// Modulo of two negative numbers
a = -9;
b = -4;
r = a % b > 0 ? a % b : abs(b) + a % b;
cout << a << " % " << b << " = " << r << "\n";
return 0;
}
// This code is contributed by Kingash
Java
// Java program for the above idea
public class PositiveModulus {
// Driver Code
public static void main(String args[])
{
int a, b, r;
// Modulo of two positive numbers
a = 9;
b = 4;
r = a % b > 0 ? a % b : Math.abs(b) + a % b;
System.out.println(a + " % " + b + " = " + r);
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
r = a % b > 0 ? a % b : Math.abs(b) + a % b;
System.out.println(a + " % "
+ b + " = " + r);
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
r = a % b > 0 ? a % b : Math.abs(b) + a % b;
System.out.println(a + " % "
+ b + " = " + r);
// Modulo of two negative numbers
a = -9;
b = -4;
r = a % b > 0 ? a % b : Math.abs(b) + a % b;
System.out.println(a + " % "
+ b + " = " + r);
}
}
C#
// C# program for the above idea
using System;
using System.Collections.Generic;
class GFG{
// Driver Code
public static void Main(string[] args)
{
int a, b, r;
// Modulo of two positive numbers
a = 9;
b = 4;
r = a % b > 0 ? a % b : Math.Abs(b) + a % b;
Console.WriteLine(a + " % " + b + " = " + r);
// Modulo of a negative number
// by a positive number
a = -9;
b = 4;
r = a % b > 0 ? a % b : Math.Abs(b) + a % b;
Console.WriteLine(a + " % " + b + " = " + r);
// Modulo of a positive number
// by a negative number
a = 9;
b = -4;
r = a % b > 0 ? a % b : Math.Abs(b) + a % b;
Console.WriteLine(a + " % " + b + " = " + r);
// Modulo of two negative numbers
a = -9;
b = -4;
r = a % b > 0 ? a % b : Math.Abs(b) + a % b;
Console.WriteLine(a + " % " + b + " = " + r);
}
}
// This code is contributed by avijitmondal1998
9 % 4 = 1
-9 % 4 = 3
9 % -4 = 1
-9 % -4 = 3