我的朋友说“mod”和“remainder”有区别。
如果是这样,在C和C++中有什么不同呢?在C中,'%'表示“mod”还是“rem”?
我的朋友说“mod”和“remainder”有区别。
如果是这样,在C和C++中有什么不同呢?在C中,'%'表示“mod”还是“rem”?
请参见https://en.wikipedia.org/wiki/Euclidean_division#Other_intervals_for_the_remainder - C语言选择将余数向0
截断(自C99起必需),强制负商具有负余数范围。即使在C89中,当标准允许使用欧几里得除法进行/
运算时。
如果商
a/b
可表示,则表达式(a/b)*b + a%b
应等于a
。
(-21/4) * 4 + (-21%4) == -21
; C99及更高版本要求(-5) * 4 + (-1)
,而不是欧几里得的-6
和3
。
-21
mod 4
得出 3
?
为什么计算式是 -21 + 4 x 6
? 为了求得 -21
除以 4
的余数,我们可以将 -21
不断加上 4
直到结果大于等于 0
,此时所加的总和就是余数。具体来说,我们可以进行以下操作:-21 + 4 = -17
-17 + 4 = -13
-13 + 4 = -9
-9 + 4 = -5
-5 + 4 = -1
-1 + 4 = 3
-21
mod 4
的结果为 3
。对于计算式 -21 + 4 x 6
,我们可以先计算 4 x 6
得到 24
,再将其加上 -21
得到 -21 + 24 = 3
,这与前面求得的 -21
mod 4
的结果相同。 - Oz Edri-21 + 4 x 6
在0到3之间。 - David Schwartz在 C 语言中,
%
表示余数1。
...
/
运算符的结果是代数商,舍弃任何小数部分...(通常称为“向零取整”)C11dr §6.5.5 6
%
运算符的操作数必须具有整数类型。C11dr §6.5.5 2
/
运算符的结果是第一个操作数除以第二个操作数的商;%
运算符的结果是余数。C11dr §6.5.5 5
什么是“mod”和“remainder”的区别?
C 语言没有定义“mod”或“modulo”运算符/函数,例如在欧几里得除法或其他模运算中使用的整数模函数。
C 定义了余数。
让我们将通过%
运算符计算出的“余数”与欧几里得“模”进行比较。
当 a
为负数时,“欧几里得模”与 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”或者叫做欧几里得除法中的模数。结果总是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;
}
关于浮点数的说明:即使被称为“fmod”,double fmod(double x, double y)
与欧几里得除法的“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)
,该函数将参数value分解为整数和小数两部分,每个部分的类型和符号与参数相同。这与“mod”讨论无关,只是名称相似。
[编辑于2020年12月]
对于那些希望在所有情况下获得适当功能的人,可以使用改进版的modulo_Euclidean()
函数,该函数检测到mod(x,0)
并且在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 中进行整数除法会得到不同的值? 因此,在一些早期的 C 编译中,%
运算可以像欧几里得除法的 “mod” 一样运行。 上述的 modulo_Euclidean()
函数也适用于这种旧的余数计算方式。
余数的符号与被除数相同,模数的符号与除数相同。
余数是两个整数相除后剩余的部分,而模数是当余数和除数异号时余数和除数之和,当余数和除数同号时则为两数相除后的剩余部分。
余数示例:
10 % 3 = 1 [这里被除数为正数,所以结果也将为正数]
-10 % 3 = -1 [这里被除数为负数,所以结果也将为负数]
10 % -3 = 1 [这里被除数为正数,所以结果也将为正数]
-10 % -3 = -1 [这里被除数为负数,所以结果也将为负数]
模数示例:
5 % 3 = 2 [这里被除数为正数,所以余数和除数都是正数。由于余数和除数都是同号的,所以结果将与余数相同]
-5 % 3 = 1 [这里被除数为负数,所以余数为负数,除数为正数。由于余数和除数异号,所以结果将为余数和除数的和 -2 + 3 = 1]
5 % -3 = -1 【被除数为正数5,因此余数也是正数,并且除数为负数。由于余数和除数异号,所以结果为余数和除数的和,即2 + (-3) = -1】
-5 % -3 = -2 【被除数为负数-5,因此余数也是负数,并且除数也是负数。由于余数和除数同号,所以结果就是余数本身】
我希望这样能够清楚地区分余数和模数。
console.log(-21 % 4 == -1);
7/-3
的商为 -2
,而 7%-3
的余数为 1
。 - chux - Reinstate Monica% 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
在模运算中,模数指的是进行算术除法后剩余的值,通常称为余数。在C/C++语言中,%被正式定义为余数运算符。例如:
7 % 3 = 1 // dividend % divisor = remainder
需要讨论的是如何处理对此%操作的负输入。现代C和C++针对此操作产生有符号余数值,结果的符号始终与被除数的符号相同,不考虑除数的符号。
7 modulo 3 --> 1
7 modulo -3 --> -2
-7 modulo 3 --> 2
-7 modulo -3 --> -1
a,b
为正数时,a%b
和a模b
具有相同的含义。C99精确地用负值定义了%
。C将其称为“余数”。在关于负数的世界中,“模数”有各种定义。C规范仅在正数的情况下使用“模数”。 - chux - Reinstate Monica