我正在阅读为什么以下代码有问题:
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
)。
我不明白这个解释或阿贝尔群引用。二进制补码加法基本上是“转换”为二进制补码的无符号模运算,对吧?
例如,如果我们有 4 位,我们的范围是 [-8, 7]。
在示例中,如果我们有 x = 7
和 y = 6
,结果溢出到 6。这不等于 y
或 x
.
那么为什么不管溢出,相等总是有效的解释呢?
“阿贝尔”群只是意味着您添加事物的顺序无关紧要 - (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。
我是一名优秀的程序员,十分优秀!