模数操作与负数

在ac程序中,我正在尝试下面的操作(只是为了检查行为)

x = 5 % (-3); y = (-5) % (3); z = (-5) % (-3); printf("%d ,%d ,%d", x, y, z); 

给我输出(2, -2 , -2)在海湾合作委员会。 我每次都期待着一个积极的结果。 模数可以是负值吗? 有人可以解释这种行为吗?

C99 要求a/b可表示时:

(a/b) * b + a%b应等于a

这在逻辑上是有道理的。 对?

让我们看看这是什么导致:


示例A. 5/(-3)-1

=> (-1) * (-3) 5%(-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)

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

我的结论是(a%b)在C中是余数运算符,而不是模运算符。

我不认为有需要检查数字是否为负数。 寻找正模的最简单的一般函数就是这个 – 它对x的正值和负值都有效。

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

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

请注意,在C89中 ,向上或向下的结果是否是实现定义的。 因为(a/b) * b + a%b等于所有标准中的a,所以涉及负操作数的%的结果也是在C89中实现定义的。

模运算的结果取决于分子的符号,因此对于yz你得到-2

这是参考

http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_14.html

整数部分

本节介绍执行整数除法的function。 这些函数在GNU C库中是多余的,因为在GNU C中,“/”运算符总是朝零调整。 但是在其他C实现中,“/”可能会带有负面的参数。 div和ldiv是有用的,因为它们指定如何将商圆:趋近于零。 其余的与分子符号相同。

在math中,这些惯例源于此,没有断言模算术应该产生积极的结果。

例如。

1 mod 5 = 1,但也可以等于-4。 也就是说,1/5产生从0开始的余数1或者从5开始产生-4(两个因子都是5)

类似地,-1 mod 5 = -1,但也可以等于4.也就是说,-1/5从-5得到0或4的余数-1。 (两个因素5)

为了进一步阅读math中的等价类 。

modulo运算符就像mod运算符,当数字是正数时,如果数字是负数则是不同的。

很多次我们被要求以10 ^ 9 + 7的模数给出答案。

让答案(在使用模之前)用“a”表示。

简单直接的规则 –

如果a是正数 ,则模10 ^ 9 + 7 = a%(10 ^ 9 + 7)

如果a为负数 ,则以10 ^ 9 + 7 = (a%(10 ^ 9 + 7))+(10 ^ 9 + 7)

如果在这样的问题中,我们发现循环的任何一步可能会计算一个超出整数范围的值(如果我们使用整数),那么我们可以在该步骤中使用模运算符。 最后的答案就好像我们只用了一次模运算符。

这是因为 – (a * b)%c =((a%c)(b%c))%c同样适用于加法和减法。

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

  1. x = 5%(-3) – 这里分子是正的,因此它的结果是2
  2. y =( – 5)%(3) – 这里分子是负的,因此得到-2
  3. z =(-5)%(-3) – 这里分子是负的,因此它的结果是-2

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