C 负数模运算
在C程序中,我尝试了以下操作(只是为了检查行为)C 负数模运算,c,gcc,modulo,negative-number,C,Gcc,Modulo,Negative Number,在C程序中,我尝试了以下操作(只是为了检查行为) 它给我的输出是gcc中的(2,-2,-2)。我每次都期待着一个积极的结果。模数可以是负的吗?有人能解释这种行为吗?模运算的结果取决于分子的符号,因此,对于y和z 这是参考资料 整数除法 本节介绍用于执行整数除法的函数。 这些函数在GNUC库中是冗余的,因为在GNUC中 “/”运算符总是向零舍入。但在另一个C 实现“/”可能会使用不同的负参数。 div和ldiv很有用,因为它们指定了如何对 商:接近零。余数的符号与 分子 C99要求当a/b可表示
它给我的输出是gcc中的
(2,-2,-2)
。我每次都期待着一个积极的结果。模数可以是负的吗?有人能解释这种行为吗?模运算的结果取决于分子的符号,因此,对于y和z
这是参考资料
整数除法
本节介绍用于执行整数除法的函数。
这些函数在GNUC库中是冗余的,因为在GNUC中
“/”运算符总是向零舍入。但在另一个C
实现“/”可能会使用不同的负参数。
div和ldiv很有用,因为它们指定了如何对
商:接近零。余数的符号与
分子
C99要求当a/b
可表示时:
(a/b)*b
+a%b
应等于a
从逻辑上讲,这是有道理的。对吧?
让我们看看这会导致什么:
示例A.
5/-3
是-1
=>(-1)*(-3)
+5%(-3)
=5
只有当5%(-3)
为2时,才会发生这种情况
例B.
(-5)/3
是-1
=>(-1)*3
+(-5)%3
=-5
只有当
(-5)%3
是-2
时,才会发生这种情况。C中的%
运算符不是模运算符,而是余数运算符
对于负值,模运算符和余数运算符不同
对于余数运算符,结果的符号与被除数的符号相同,而对于模运算符,结果的符号与除数相同
C将a%b
的%
操作定义为:
a == (a / b * b) + a % b
使用
/
整数除法,截断方向为0
。这是对0
(而不是对负有限性)进行的截断,它将%
定义为余数运算符而不是模运算符。基于C99规范:a==(a/b)*b+a%b
我们可以编写一个函数来计算(a%b)==a-(a/b)*b
int remainder(int a, int b)
{
return a - (a / b) * b;
}
对于模运算,我们可以使用以下函数(假设b>0
)
intmod(inta,intb)
{
int r=a%b;
返回r<0?r+b:r;
}
我的结论是C中的
a%b
是余数运算,而不是模运算。其他答案在C99或更高版本中解释过,涉及负操作数的整数除法总是向零截断
int mod(int m, float n)
{
return m - floor(m/n)*n;
}
请注意,在C89中,向上或向下四舍五入的结果是由实现定义的。因为在所有标准中,
(a/b)*b+a%b
等于a
,涉及负数操作数的%
的结果也是在C89中定义的实现。我认为不需要检查该数字是否为负数
求正模的一个简单函数是-
编辑:假设数学中的
N>0
和N+N-1是这些约定的根源,没有断言模运算会产生积极的结果
例如
1 mod 5=1,但也可以等于-4。也就是说,1/5从0得到余数1或从5得到-4。(两个因素均为5)
同样地,
-1 mod 5=-1,但也可以等于4。也就是说,-1/5从0得到余数-1或从-5得到余数4。(两个因素均为5)
为了进一步阅读,请研究数学 模运算符给出余数。
c中的模运算符通常取分子的符号
x=5%(-3)-此处分子为正,因此结果为2
y=(-5)%(3)-此处分子为负数,因此结果为-2
z=(-5)%(-3)-此处分子为负数,因此结果为-2
此外,模(余数)运算符只能用于整数类型,不能用于浮点。根据第6.5.5节
乘法运算符
,必须满足以下条件:
(a / b) * b + a % b = a
结论
余数运算结果的符号,根据
对于C99,与股息相同
让我们看一些例子(除数/除数
):
当只有股息为负时
当除数为负时
当除数和被除数都为负数时
6.5.5乘法运算符 语法
cast表达式
乘法表达式*cast表达式
乘法表达式/强制转换表达式
乘法表达式%cast表达式
a/b
是可表示的,
表达式(a/b)*b+a%b
应等于int modulo(int x,int N){
return (x % N + N) %N;
}
(a / b) * b + a % b = a
(-3 / 2) * 2 + -3 % 2 = -3
(-3 / 2) * 2 = -2
(-3 % 2) must be -1
(3 / -2) * -2 + 3 % -2 = 3
(3 / -2) * -2 = 2
(3 % -2) must be 1
(-3 / -2) * -2 + -3 % -2 = -3
(-3 / -2) * -2 = -2
(-3 % -2) must be -1
// a % b
7 % 3 --> 1
7 % -3 --> 1
-7 % 3 --> -1
-7 % -3 --> -1
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;
}
modulo_Euclidean( 7, 3) --> 1
modulo_Euclidean( 7, -3) --> 1
modulo_Euclidean(-7, 3) --> 2
modulo_Euclidean(-7, -3) --> 2
5 % -3
{ 0, -2, -1 }
0 => 0, 1 => -2, 2 => -1, 3 => 0, 4 => -2, 5 => -1
int mod(int m, float n)
{
return m - floor(m/n)*n;
}