比较两个数字x,y;如果x> y我返回1,否则返回0.我试图只使用按位运算符,例如>> << 〜! &安培; | ^ +。
到目前为止,我得到了这个:
int greaterThan(int x,int y) {
return ((~(x-y))>>31);
}
因此,如果xy为负,则最高有效位为1.因此,我将其否定为0并将其移位以使其返回0.如果xy为正,则最高有效位为0.否定它得到1并将其转移到返回1.它似乎不起作用。我这样做错了还是遗失了什么?
答案 0 :(得分:3)
由于以下几个原因,您的方法不起作用:
假设x
和y
是有符号值,减法可能会溢出。根据C标准,这不仅会导致未定义的行为,而且在溢出包装的典型实现中,它会产生错误的结果。例如,如果x
为INT_MIN
且y
为1
,则x-y
将产生INT_MAX
,其未设置高位。
如果x
和y
是无符号值,那么x=UINT_MAX
和y=0
就是您得到错误答案的示例。您必须对x
和y
的值施加条件(例如,既没有高位设置),以便此测试有效。
归结为,为了通过测试“高位”执行比较,您需要比所比较的值中的位数多一位。在合理的CISC-ish架构的汇编语言中,进位标志提供了这个额外的位,并且特殊的条件跳转指令(以及进位/借位指令)能够读取进位标志的值。但是,C无法访问这样的进位标志。一种替代方法可能是使用更大的整数类型(如long long
),以便您可以在结果中获得额外的位。好的编译器会将其转换为进位标志的读取,而不是实际执行更大的算术运算。
答案 1 :(得分:1)
C Standard(1999),第6.5.7章按位移位算子,第5段:
E1>的结果> E2是E1右移E2位位置。如果E1具有无符号类型 或者如果E1具有带符号类型和非负值,则结果的值为积分 E1 / 2E2商的一部分。如果E1有签名类型和负值,则 结果值是实现定义的。
即,负数位右移的结果是实现定义的。一种可能性是“符号位”被复制到右边的位中,这就是GCC似乎要做的事情(因为它导致所有位设置为-1)。
答案 2 :(得分:0)
@Dan,你能否在第一篇文章中澄清你的问题,即你可以使用什么以及你不能使用什么(在你的评论中你提到你不能使用if
/ {{1等等)。
无论如何,如果你想摆脱意外的else
,你应该考虑在转移前将你的价值转换为-1
。但这并不能使您的解决方案完全正确。试着考虑检查数字的符号位(例如unsigned int
的第一位是x
而0
的第一位是y
那么你可以确定x> y )。