为什么7%-5给出2但-7%5给-2? 这两种情况都不应该是-2吗?
请解释下面的原因,在数学上,两种情况下正确的答案是-2
:
int a=7%-5; //Assigns 2 to a int a=-7%5; //Assigns -2 to a
代码在C中。
7 / -5 = -1
,其余为2
,因为-1 * -5 + 2 = 5 + 2 = 7
。
-7 / 5 = -1
,余数为-2
,因为-1 * 5 + (-2) = -5 - 2 = -7
。
C ++中的%
是余数运算符(正数用作数学模运算符)。
因为在大多数C实现中,整数除法截断并且不向负无穷大舍入。 您的实现似乎也是其中之一。
a % b = a - (a / b) * b
所以
7 % (-5) = 7 - (7 / -5) * (-5)
是的
7 % (-5) = 7 - (-1) * (-5) = 7 - 5 = 2
在C 90或C ++ 98标准中没有规定具有负数的数字的模数应该是什么。 要么是可以接受的。 它在C 99和C ++ 2011中定义,但具有与被除数相同的符号。
有关模数和余数之间差异的讨论,请参阅此文章:
也是维基百科上的这篇文章,它引用了标准的状态。
答案不是数学的,而是传统的。 理论上模数运算符总是有两种可能的结果,即负面和正面。
7 % 5
是2
或-3
。
在数学中,大多使用积极的结果。 在编程中取决于编程语言。
原始C未指定使用哪一个。 积极的数字你总是得到积极的模块; 带负数的结果取决于使用的编译器。
C-99指定modula的结果应与被除数具有相同的符号。 这解释了你观察到的行为。
您可以在此处查看不同编程语言的模运算符的结果 。
规则是r = a - (a/b) * b
所以
2 = 7 - (7/-5)*(-5) // note: 7/-5 is -1
具有负值的模运算在IT中没有单一的定义。 有三种不同的算法:
- 截断分裂
- 地板师
- 欧几里德分裂
当操作数为正时提供相同的结果,但当它们为负时提供不同的结果。
更多信息
许多实现使用截断除法,其中商通过截断q = trunc(a / n)定义,换句话说,它是精确理性商在0方向上的第一个整数,其余为r = a – n q 。 非正式地说,商是“向零舍入”,因此余数与被除数具有相同的符号。
Knuth描述了浮动除法,其中商由地板函数q = floor(a / n)定义,余数r为
r = a - nq = a - n \left\lfloor {a \over n} \right\rfloor.
这里的商总是向下舍入(即使它已经是负数),其余的符号与除数相同。
Raymond T. Boute介绍了欧几里德定义,其中余数总是正或0,因此与除法算法一致(参见欧几里德分裂)。 该定义在表中标记为“始终为正”。 设q为a和n的整数商,则:
在C中,问题是算法是实现定义的 ,因此如果您希望程序是可移植的,则需要为负数滚动自己的模运算。