C在减法过程中检查溢出
我一直在尝试确定在减去两个32位数字时是否存在溢出。我得到的规则是:C在减法过程中检查溢出,c,bitwise-operators,integer-overflow,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
Can only use: ! ~ & ^ | + << >>
* Max uses: 20
Example: subCheck(0x80000000,0x80000000) = 1,
* subCheck(0x80000000,0x70000000) = 0
No conditionals, loops, additional functions, or casting
我现在意识到我不能在实际函数(-)中使用减法,所以我的整个函数无论如何都是无用的。如何使用与减法不同的方法,并仅使用位运算来确定是否存在溢出?为了避免未定义的行为,我将假设整数以二的补码表示,从您对
sX
、sY
和sDif
的计算中推断出来。我还将假定sizeof(int)
为4。如果只处理32位整数,则最好使用int32\u 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.
谢谢大家的帮助!以下是我解决问题的方法:
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。我想知道是什么学校给出了这些完全没有大脑的作业。至少它介绍了按位运算和两个负值的互补存储。
a-b
溢出发生时。OP尝试只使用位运算符和进行求解代码>依赖于UB或实现定义的行为。我认为如果不依赖于未定义的行为,这是不可能的。基本上,您的目标是按照chux编写的方式表示检查,但只使用登记的运算符。我不知道如何实现返回值1
是否意味着有溢出或没有溢出?P=正N=负。P-P不能溢出。N-N不能溢出。如果减法结果为负,则P-N溢出。如果减法的结果为正,则N-P溢出。您的代码实际上执行溢出的操作,并随后进行检查。这是行不通的:有符号整数溢出在C中有未定义的行为。它当然适用。二的补码是一个正交关系。我的意思是C实现可以使用二的补码、一的补码或符号/大小。无论是哪种类型,有符号整数溢出都有未定义的行为。不同意。C不要求使用2的补码的平台在溢出时定义良好,正如这个答案所希望的那样。看见
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));