C在减法期间检查溢出

时间:2018-10-17 19:25:45

标签: c bitwise-operators integer-overflow

我一直在尝试确定两个32位的数字相减时是否有溢出。我得到的规则是:

Can only use: ! ~ & ^ | + << >>
 *   Max uses: 20
Example: subCheck(0x80000000,0x80000000) = 1,
 *       subCheck(0x80000000,0x70000000) = 0
No conditionals, loops, additional functions, or casting

到目前为止我有

int dif = x - y; // dif is x - y
int sX = x >> 31; // get the sign of x
int sY = y >> 31; // get the sign of y
int sDif = dif >> 31; // get the sign of the difference
return (((!!sX) & (!!sY)) | (!sY)); // if the sign of x and the sign of y 
                                    // are the same, no overflow. If y is 
                                    // 0, no overflow.

我现在意识到我不能在实际函数(-)中使用减法,因此我的整个函数反正毫无用处。我该如何使用与减法不同的方法,并仅通过按位运算来确定是否存在溢出?

2 个答案:

答案 0 :(得分:1)

谢谢大家的帮助!这是我想出的解决问题的方法:

int ny = 1 + ~y; // -y
int dif = x + ny; // dif is x - y
int sX = x >> 31; // get the sign of x
int sY = y >> 31; // get the sign of -y
int sDif = dif >> 31; // get the sign of the difference
return (!(sX ^ sY) | !(sDif ^ sX));

每种情况下我都尝试过。我更改了@HackerBoss的建议,方法是获取y而不是ny的符号,然后反转return语句中的两个检查。这样,如果符号相同,或者结果的符号和x的符号相同,则返回true。

答案 1 :(得分:0)

为避免未定义的行为,我将假定整数用二进制补码表示,该补数由您对sXsYsDif的计算得出。我还将假设sizeof(int)为4。如果仅使用32位整数,则使用int32_t可能会更好,因为int的大小会因平台而异。

由于允许使用加法,因此可以将减法视为对数字的求反。可以通过翻转所有位并加一个来取反以二进制补码存储的数字。这给出了以下修改的代码:

int ny = 1 + ~y; // -y
int dif = x + ny; // dif is x - y
int sX = x >> 31; // get the sign of x
int sNY = ny >> 31; // get the sign of -y
int sDif = dif >> 31; // get the sign of the difference
return ((sX ^ sNY) | (~sDif ^ sX)); // if the sign of x and the sign of y 
                                    // are the same, no overflow. If the
                                    // sign of dif is the same as the signs
                                    // of x and -y, no overflow.