检查已签名的加法和abelian组的溢出

时间:2014-09-21 21:01:08

标签: c types integer integer-overflow integer-arithmetic

我正在阅读以下代码为何出错:

int tadd_ok ( int x, int y ) {  
    int sum = x + y;  
    return ( sum - x == y ) && ( sum - y == x );  
}  

解释是,两个补语加法形成一个阿贝尔群,所以表达式为 无论加法是否溢出,(x + y) - x评价为y(x + y) - y)的评分为x)。

我不理解这个解释或阿贝尔群体的参考。二进制补码基本上是无符号模运算,它被转换成#34;对于两个补充,对吗? 因此,例如,如果我们有4位,我们有范围[-8,7]。
在示例中,如果我们有x = 7y = 6,则结果溢出为6.而且这不等于yx
那么,为什么解释说,无论溢出,等式总是有效的?

2 个答案:

答案 0 :(得分:3)

“阿贝尔”组只是意味着你添加东西的顺序无关紧要 - (a + b)+ c = a +(b + c)和(a + b)==(b + a)。

这对于C中的整数是正确的。技术上是正确的,因为@ouah指出溢出是未定义的,但这是为了在不使用两个恭维数学的处理器上轻松支持C标准。大多数人都这样做。

关于那些,除非在编译器中发生非常奇怪的事情(或者不那么奇怪,但是优化 - 感谢@ouah),无符号数学将作为一个阿贝尔群。

在您的示例中,7 + 6 = 0111 + 0110 == 1101是 - (0010 + 1)= -3。在两个补码签名系统中,负数“以二进制计数”:1111为-1。减去1010,或0101 + 1 = 6。

答案 1 :(得分:1)

这是个老问题,但希望我的回答对某人有用。

这是因为要修复正溢出(当 x + y > TYPE_MAX 时)我们需要从总和中减去 2^n 并修复负溢出(当 x + y < TYPE_MIN 时)我们需要添加 { {1}}(需要一堆数学语句来说明这一点,所以我决定不将它们包含在答案中)。

因此,如果 2^n 正溢出,x + y 实际上等于 sum。在此之后,当我们执行比较时,我们从 x + y - 2^n 中减去 x,这会导致负溢出,因此我们有 sum 实际上等于 sum - x。因此,sum - x + 2^n。另一个介词也会发生同样的情况。