为什么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中,问题是算法是实现定义的 ,因此如果您希望程序是可移植的,则需要为负数滚动自己的模运算。