4

对于家庭作业,我必须在 C 中编写一个函数,将两个有符号整数相加,但如果存在正溢出则返回 INT_MAX,如果存在负溢出则返回 INT_MIN。对于可以使用的运算符,我必须遵守非常严格的限制。所有整数都是二进制补码形式,右移是算术,整数大小是可变的(我可以用 sizeof(int)<<3 找到它)。我不能使用条件语句、循环、比较运算符或强制转换。我只能使用按位和逻辑运算符、加法和减法、相等测试以及整数常量 INT_MAX 和 INT_MIN。

我知道如果两个输入具有相同的符号并且结果具有不同的符号,则可以检测到溢出。我已经到了有一个标志显示等式是否溢出的地步。我不知道如何从那里到达最终产品。这是我到目前为止所拥有的:

int saturating_add(int x, int y){
    int w = sizeof(int)<<3;
    int result = x+y;
    int signX = (x>>w-1)&0x01;//Sign bit of X
    int signY = (y>>w-1)&0x01;//Sign bit of Y
    int resultSign = (result>>w-1)&0x01; //Sign bit of result
    int canOverflow = ~(signX ^ signY); //If they're the same sign, they can overflow
    int didOverflow = (resultSign^signX)&canOverflow; //1 if input signs are same and result sign different, 0 otherwise

}

我正在尝试遵循C (HW) 中按位饱和加法中显示的答案,但我被困在必须为除符号位之外的所有位填充一个整数的部分(1 到 0111。 .11 和 0 转到 0000.00)。我不知道“班次和 OR 的组合”会是什么。

4

1 回答 1

2

我想你误解了答案。您应该做的是将符号位扩展到所有位,包括 MSB。这可以通过获取包含符号位的 int 来完成,例如didOverflow,并将其补码加 1。

然后你找到在溢出的情况下应该返回哪个溢出值。这可以通过INT_MAX扩展的 XORing 来完成signX(或者signY,两者都可以)。我们称这个值overflow。最后,改变overflowresult像这样:

overflow := (extended didOverflow) AND overflow
result := (NOT (extended didOverflow)) AND result

现在,在这些赋值之后,如果扩展didOverflow是 1...1,那么overflow显然将保持不变。result,另一方面,将等于 0。

但如果didOverflow为 0...0,则相反:overflow现在为 0,而result保持不变。

在第一种情况下(其中didOverflow1...1,表示存在溢出),overflow OR result等于overflow. 在第二种情况下(我们没有溢出),overflow OR resultequals result。所以无论哪种方式,overflow OR result都会给我们正确的价值。

于 2013-10-07T01:28:55.417 回答