请解释以下原因,在数学上,两种情况下的正确答案都是-2
:
int a=7%-5; //Assigns 2 to a
int a=-7%5; //Assigns -2 to a
代码在C。
答案 0 :(得分:11)
7 / -5 = -1
剩余2
,因为-1 * -5 + 2 = 5 + 2 = 7
。
-7 / 5 = -1
剩余-2
,因为-1 * 5 + (-2) = -5 - 2 = -7
。
%
是一个余数运算符(正数用作数学模运算符)。
答案 1 :(得分:3)
因为在大多数C实现中,整数除法截断并且不向负无穷大舍入。您的实现似乎也是其中之一。
a % b = a - (a / b) * b
所以
7 % (-5) = 7 - (7 / -5) * (-5)
是
7 % (-5) = 7 - (-1) * (-5) = 7 - 5 = 2
答案 2 :(得分:0)
在C 90或C ++ 98标准中没有指明带负数的数字的模数应该是什么。要么是可以接受的。它在C 99和C ++ 2011中定义,但与被除数具有相同的符号。
有关模数和余数之间差异的讨论,请参阅本文:
这篇关于维基百科的文章,它引用了标准状态。
答案 3 :(得分:0)
答案不是数学的,而是传统的。理论上模数运算符总是有两种可能的结果,即负面和正面。
7 % 5
是2
或-3
。
在数学中,大多使用积极的结果。在编程中取决于编程语言。
原始C未指定使用哪一个。积极的数字你总是得到积极的模块;如果是负数,则结果取决于所使用的编译器。
C-99指定modula的结果应与被除数具有相同的符号。这解释了你观察到的行为。
您可以在不同的编程语言here中看到模运算符的结果。
答案 4 :(得分:0)
规则为r = a - (a/b) * b
所以
2 = 7 - (7/-5)*(-5) // note: 7/-5 is -1
答案 5 :(得分:0)
具有负值的模运算在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中,问题是算法是实现定义, 所以你需要为负数滚动你自己的模运算 如果你想让你的程序可移植。