187

我的朋友说“mod”和“remainder”之间存在差异。

如果是这样,C 和 C++ 有什么区别?'%' 在 C 中是指“mod”还是“rem”?

4

7 回答 7

180

模数和余数之间存在差异。例如:

-21mod43因为-21 + 4 x 63

-21除以余数4为.-5-1

对于正值,没有区别。

于 2012-12-03T12:54:58.110 回答
62

'%' 在 C 中是指“mod”还是“rem”?

在 C 中,%余数1

...,/运算符的结果是任何小数部分被丢弃的代数商...(这通常称为“向零截断”。) C11dr §6.5.5 6

运算符的操作数%应为整数类型。C11dr §6.5.5 2

运算符的结果/是第一个操作数除以第二个的商;%运算符的结果是余数... C11dr §6.5.5 5


“mod”和“remainder”有什么区别?

C 没有定义“mod”或“模”运算符/函数,例如欧几里得除法其他模中使用的整数模函数。

C 定义了余数

让我们将每个%运算符的“余数”与欧几里德的“mod”进行比较。

当为负时,“欧几里得模”与 C 的a%b运算不同。a

 // a % b, the remainder after an integer division that truncates toward 0.
 7 %  3 -->  1  
 7 % -3 -->  1  
-7 %  3 --> -1  
-7 % -3 --> -1   

欧几里得除法中的“模”或模。结果始终为 0 或正数。

 7 modulo  3 -->  1
 7 modulo -3 -->  1
-7 modulo  3 -->  2
-7 modulo -3 -->  2

候选模代码:

int modulo_Euclidean(int a, int b) {
  int m = a % b;
  if (m < 0) {
    // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
    m = (b < 0) ? m - b : m + b;
  }
  return m;
}

关于浮点数的注意事项:double fmod(double x, double y),虽然叫做“fmod”,但它与欧几里德除法“mod”不同,但类似于C整数余数:

这些fmod 函数计算 的浮点余数x/y。C11dr §7.12.10.1 2

fmod( 7,  3) -->  1.0
fmod( 7, -3) -->  1.0
fmod(-7,  3) --> -1.0
fmod(-7, -3) --> -1.0

消歧:C 也有一个类似的命名函数double modf(double value, double *iptr),它将参数值分成整数和小数部分,每个部分都具有与参数相同的类型和符号。除了名称相似性之外,这与这里的“mod”讨论几乎没有关系。


[编辑 2020 年 12 月]

对于那些在所有情况下都需要适当功能的人,改进modulo_Euclidean()了 1)检测mod(x,0)和 2)使用modulo_Euclidean2(INT_MIN, -1). 受到具有完全定义行为的 4 种不同模数实现的启发。

int modulo_Euclidean2(int a, int b) {
  if (b == 0) TBD_Code(); // perhaps return -1 to indicate failure?
  if (b == -1) return 0; // This test needed to prevent UB of `INT_MIN % -1`.
  int m = a % b;
  if (m < 0) {
    // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
    m = (b < 0) ? m - b : m + b;
  }
  return m;
}

1在 C99 之前,C 的定义%仍然是除法的余数,但/允许负商向下舍入而不是“向零截断”。请参阅为什么在 C89 中得到不同的整数除法值?. 因此,对于一些 C99 之前的编译,%代码可以像欧几里得除法“mod”一样工作。以上modulo_Euclidean()内容也适用于这种替代的老式剩余部分。

于 2013-12-17T15:51:38.923 回答
15

余数的符号与除数相同,模数的符号与除数相同。

余数只是两个整数之间的算术除法后的剩余部分,而模数是余数和除数的和,当它们的符号相反时,以及当余数和除数都具有相同符号时,算术除法后的剩余部分。

余数示例:

10 % 3 = 1 [这里可除数是 10,它是正符号的,所以结果也将是正符号的]

-10 % 3 = -1 [这里可除数是-10,它是负号的,所以结果也将是负号的]

10 % -3 = 1 [这里可除数是 10,它是正符号的,所以结果也将是正符号的]

-10 % -3 = -1 [这里可除数是-10,它是负号的,所以结果也将是负号的]

模数示例:

5 % 3 = 2 [这里可除数是5,它是正符号的,所以余数也将是正符号的,除数也是正符号的。由于余数和除数的符号相同,结果将与余数相同]

-5 % 3 = 1 [这里可除数是-5,它是负号的,所以余数也将是负号的,除数是正号的。由于余数和除数的符号相反,结果将是余数和除数之和 -2 + 3 = 1]

5 % -3 = -1 [这里可除数是5,它是正符号的,所以余数也将是正符号,除数是负符号。由于余数和除数的符号相反,结果将是余数和除数之和 2 + -3 = -1]

-5 % -3 = -2 [这里可除数是-5,它是负号的,所以余数也将是负号的,除数也是负号的。由于余数和除数的符号相同,结果将与余数相同]

我希望这将清楚地区分余数和模数。

于 2021-01-06T23:44:54.050 回答
8

在 C 和 C++ 以及许多语言%中,余数不是模运算符。

例如在运算-21 / 4中整数部分是-5,小数部分是-.25。余数是除数的小数部分,所以我们的余数是-1。JavaScript 使用余数运算符并确认这一点

console.log(-21 % 4 == -1);

模数运算符就像您有一个“时钟”。想象一个圆,分别在 12 点钟、3 点钟、6 点钟和 9 点钟位置有值 0、1、2 和 3。以顺时针方向步进商时间使我们得到模运算的结果,或者,在我们的示例中,逆时针方向为负商,得到 3。

注意:模数始终与除数同号,余数与商同号。当至少一个为负时,将除数和余数相加得到模数。

于 2019-09-04T00:42:33.060 回答
3
% is a remainder(leftover after dividend / divisor) NOT modulus. 

You could write your own modulus function using the remainder(%) by the relation

  ((n%m)+m)%m

  where `n` is the given number and `m` is the modulus

Find below the difference between the remainder and modulus values for the range n = (-7,7) and m = 3

n       -7 -6 -5 -4 -3 -2 -1  0  1  2  3  4  5  6  7  
------------------------------------------------------------------------- 
%(-m)   -1  0 -2 -1  0 -2 -1  0  1  2  0  1  2  0  1  =>  remainder
% m     -1  0 -2 -1  0 -2 -1  0  1  2  0  1  2  0  1  =>  remainder
mod m    2  0  1  2  0  1  2  0  1  2  0  1  2  0  1  =>  ((n%m)+m)%m
mod(-m) -1  0 -2 -1  0 -2 -1  0 -2 -1  0 -2 -1  0 -2  =>  ((n%m)+m)%m

Tips to remember:

n%(-m)   = +(remainder)
(-n)%(m) = -(remainder)
sign of 'm' doesn't matter

n mod (-m) = -(result)
(-n) mod m = +(result)
sign of 'n' doesn't matter

For +ve 'n' and '%(-m)' or '%m' or 'mod m' gives the same remainder
于 2021-03-24T08:11:13.753 回答
3

模数,在您所指的模算术中,是算术除法后剩余的值或剩余值。这通常称为余数。% 正式地是 C / C++ 中的余数运算符。例子:

7 % 3 = 1  // dividend % divisor = remainder

剩下要讨论的是如何处理这个 % 操作的负输入。现代 C 和 C++ 会为此运算生成一个有符号余数,其中结果的符号始终与被除数输入匹配,而不考虑除数输入的符号。

于 2018-01-12T13:03:18.993 回答
-3

在数学中,模运算的结果是欧几里得除法的余数。然而,其他约定也是可能的。计算机和计算器有多种存储和表示数字的方式;因此,他们对模运算的定义取决于编程语言和/或底层硬件。

 7 modulo  3 -->  1  
 7 modulo -3 --> -2 
-7 modulo  3 -->  2  
-7 modulo -3 --> -1 
于 2016-06-14T18:25:38.240 回答