C语言 “模”和“余数”有什么区别?

zy1mlcev  于 2023-02-07  发布在  其他
关注(0)|答案(7)|浏览(828)

我的朋友说“mod”和“remainder”是有区别的。
如果是这样,C和C++的区别是什么?“%”在C中是“mod”还是“rem”?

laik7k3q

laik7k3q1#

模数和余数之间存在差异。例如:
-214等于3,因为-21 + 4 x 6等于3
但是-21除以4得到-5,余数为-1
对于正值,没有差异。

s6fujrry

s6fujrry2#

在C语言中," %"是指"mod"还是"rem"?
在C中,%余数1。
...,/运算符的结果是去掉任何小数部分的代数商...(这通常被称为"向零截断")C11dr § 6.5.5 6
%运算符的操作数必须是整数类型。C11dr § 6.5.5 2
/运算符的结果是第一个操作数除以第二个操作数所得的商;%运算符的结果是余数... C11dr § 6.5.5 5
"模"和"余数"有什么区别?
C没有定义"mod"或"modulo"运算符/函数,例如Euclidean divisionother modulo中使用的整数模函数。
C定义 * 余数 *。
让我们将每个%运算符的"余数"与欧几里德"mod"进行比较。
a为负时,"欧几里得mod"不同于C的a%b运算。

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

欧几里德除法中的"mod"或"modulo"。结果总是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

Disambiguation:C也有一个类似的命名函数double modf(double value, double *iptr),它将参数值分为整数和小数部分,每个部分都与参数具有相同的类型和符号,除了名称相似之外,这与这里讨论的"mod"没有什么关系。
[Edit二○二○年十二月】
对于那些希望在所有情况下都能正常工作的用户,改进的modulo_Euclidean()可1)检测mod(x,0)和2)使用modulo_Euclidean2(INT_MIN, -1)获得良好的无UB结果。

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对%的定义仍然是除法的 * 余数 *,但是/允许负商向下舍入,而不是"向零截断"。参见Why do you get different values for integer division in C89?。因此,在C99之前的一些编译中,%代码可以像欧几里得除法"mod"一样工作。上面的modulo_Euclidean()也可以使用这种替代的老式余数。

y53ybaqx

y53ybaqx3#

余数的符号将与被除数的符号相同,并且模数的符号将与除数的符号相同。
余数只是两个整数之间算术除法后的剩余部分,而模是余数和除数符号相反时的和,以及余数和除数符号相同时算术除法后的剩余部分。

余额示例:

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,带负号,因此余数也带负号,除数也带负号。由于余数和除数的符号相同,因此结果与余数相同]
我希望这将清楚地区分余数和模。

zphenhs4

zphenhs44#

在C和C++以及许多语言中,%是余数而不是模运算符。
例如,在-21 / 4运算中,整数部分是-5,小数部分是-.25。余数是小数部分乘以除数,因此余数是-1。JavaScript使用余数运算符并对此进行确认

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

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

**注意:**模始终与除数的符号相同,余数与商的符号相同。当除数和余数中至少有一个为负时,将它们相加即可得到模。

9gm1akwq

9gm1akwq5#

模,在模运算中,你所指的是剩余的值或算术除法后的剩余值。这通常被称为余数。%在C / C++中是形式上的余数运算符。例如:

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

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

dl5txlt9

dl5txlt96#

% is a remainder(leftover after dividend / divisor) NOT modulus.

您可以通过以下关系式使用余数(%)编写自己的模函数

((n%m)+m)%m

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

在n =(-7,7)和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
  • 要记住的提示:*
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
vsnjm48y

vsnjm48y7#

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

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

相关问题