在一个C程序中,我尝试了以下操作(只是为了检查行为)

 x = 5 % (-3);
 y = (-5) % (3);
 z = (-5) % (-3); 

printf("%d ,%d ,%d", x, y, z); 

在gcc中输出为(2,-2,-2)我以为每次都会有积极的结果。模量可以是负的吗?有人能解释一下这种行为吗?


当前回答

C中的%操作符不是模操作符而是余数操作符。

模运算符和余数运算符不同于负值。

对于余数运算符,结果的符号与被除数(分子)的符号相同,而对于模运算符,结果的符号与除数(分母)的符号相同。

C将a % b的%操作定义为:

  a == (a / b * b) + a % b

用/表示整型除法,并截断为0。这是对0(而不是负无穷)的截断,它将%定义为余数运算符而不是模运算符。

其他回答

其他答案已经在C99或更高版本中解释过,涉及负操作数的整数除法总是截断为零。

注意,在C89中,结果向上舍入还是向下舍入是由实现定义的。因为(a/b) * b + a%b在所有标准中都等于a,包含负操作数的%的结果也是在C89中实现定义的。

我认为没有必要检查数字是否为负。

求正模的一个简单函数是这个-

编辑:假设N > 0和N + N - 1 <= INT_MAX

int modulo(int x,int N){
    return (x % N + N) %N;
}

这对x的正负都成立。

原始p.s.:也正如@chux指出的那样,如果你的x和N可能分别达到INT_MAX-1和INT_MAX,只需将int替换为long long int。

如果它们也越过了long long的限制(即在LLONG_MAX附近),那么你应该分别处理正的和负的情况,在这里的其他答案中描述。

C中的%操作符不是模操作符而是余数操作符。

模运算符和余数运算符不同于负值。

对于余数运算符,结果的符号与被除数(分子)的符号相同,而对于模运算符,结果的符号与除数(分母)的符号相同。

C将a % b的%操作定义为:

  a == (a / b * b) + a % b

用/表示整型除法,并截断为0。这是对0(而不是负无穷)的截断,它将%定义为余数运算符而不是模运算符。

模算子给出余数。 c中的模算子通常取分子的符号

X = 5%(-3)这里分子是正的,所以结果是2 Y =(-5) %(3)分子为负,结果为-2 Z =(-5) %(-3)这里分子是负的所以结果是-2

此外,模(余数)运算符只能用于整型,不能用于浮点数。

根据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)

int mod(int a, int b)
{
    int r = a % b;
    return r < 0 ? r + b : r;
}

我的结论是C中的a % b是一个余数运算,而不是一个模运算。