模数操作与负数
在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中实现定义的。
模运算的结果取决于分子的符号,因此对于y和z你得到-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中的模运算符通常取分子的符号
- x = 5%(-3) – 这里分子是正的,因此它的结果是2
- y =( – 5)%(3) – 这里分子是负的,因此得到-2
- z =(-5)%(-3) – 这里分子是负的,因此它的结果是-2
另外模数(余数)运算符只能用于整型,不能用于浮点型。