简体   繁体   English

使用C(HW)中的按位运算符饱和有符号整数加法

[英]Saturating signed integer addition with only bitwise operators in C (HW)

For a homework assignment, I have to write a function in C that adds together two signed integers, but returns INT_MAX if there would be positive overflow and INT_MIN if there would be negative overflow. 对于家庭作业,我必须在C中编写一个函数,它将两个有符号整数相加,但如果存在正溢出则返回INT_MAX,如果存在负溢出则返回INT_MIN。 I have to follow very strict restrictions in what operators I can use. 在我可以使用的操作符中,我必须遵循非常严格的限制。 All integers are in two's complement form, right shifts are arithmetic, and the integer size is variable (I can find it with sizeof(int)<<3). 所有整数都是二进制补码形式,右移是算术运算,整数大小是可变的(我可以用sizeof(int)<< 3)找到它。 I can't use contitionals, loops, comparison operators, or casting. 我不能使用contitionals,循环,比较运算符或转换。 I can only use bitwise and logical operators, addition and subtraction, equality tests, and the integer constants INT_MAX and INT_MIN. 我只能使用按位和逻辑运算符,加法和减法,相等测试以及整数常量INT_MAX和INT_MIN。

I know that overflow can be detected if the two inputs have the same sign and the result has a different sign. 我知道如果两个输入具有相同的符号并且结果具有不同的符号,则可以检测到溢出。 I've gotten to the point where I have a flag showing if the equation did overflow. 我已经达到了一个标志,显示方程式是否溢出。 I have no idea how to get from there to the end product. 我不知道如何从那里到最终产品。 This is what I have so far: 这是我到目前为止:

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

}

I'm trying to follow the answer shown at Bitwise saturated addition in C (HW) , but I'm stuck on the part where I have to fill an integer with the same bit for all but the sign bit (1 goes to 0111..11 and 0 goes to 0000.00). 我试图按照C(HW)中的Bitwise饱和加法所示的答案,但是我被困在我必须用除了符号位(1到0111)之外的所有相同位填充整数的部分。 .11和0转到0000.00)。 I have no idea what the "combination of shifts and ORs" would be. 我不知道“轮班和OR的组合”会是什么。

I think you misunderstood the answer. 我觉得你误解了答案。 What you should do is extend the sign bit to all of the bits, including the MSB. 你应该做的是将符号位扩展到所有位,包括MSB。 This can be accomplished by taking the int holding the sign bit, eg didOverflow , and add 1 to its complement. 这可以通过将int保持符号位(例如didOverflow )并将其添加到其补码来实现。

Then you find which overflow value should be returned in the case that there is an overflow. 然后,您会发现在出现溢出的情况下应返回哪个溢出值。 That can be done by XORing INT_MAX with extended signX (or signY , both will work). 这可以通过XORing INT_MAX与扩展signX (或signY ,两者都可以)来完成。 Let's call this value overflow . 我们称这个值为overflow Finally, alter overflow and result like this: 最后,改变overflowresult如下:

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

Now, after these assignments, if the extended didOverflow is 1...1, then overflow will obviously remain unchanged. 现在,在这些赋值之后,如果扩展的didOverflow是1 ... 1,那么overflow显然将保持不变。 result , on the other hand, will be equal 0. result ,在另一方面,将等于0。

But if didOverflow is 0...0, then the opposite applies: overflow is now 0, while result remains unchanged. 但是如果didOverflow是0 ... 0,则相反的情况适用: overflow现在为0,而result保持不变。

In the first case (where didOverflow was 1...1, signaling that there was an overflow), overflow OR result equals overflow . 在第一种情况下(其中didOverflow为1 ... 1,表示存在溢出), overflow OR result等于overflow In the second case (where we have no overflow), overflow OR result equals result . 在第二种情况下(我们没有溢出), overflow OR result等于result So either way, overflow OR result will give us the correct value. 所以无论哪种方式, overflow OR result都会给我们正确的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM