如何比较两个数字,看哪个更大

时间:2010-09-27 04:47:23

标签: c numbers bit-manipulation

比较两个数字x,y;如果x> y我返回1,否则返回0.我试图只使用按位运算符,例如>> << 〜! &安培; | ^ +。

到目前为止,我得到了这个:

int greaterThan(int x,int y) {
return ((~(x-y))>>31);
}

因此,如果xy为负,则最高有效位为1.因此,我将其否定为0并将其移位以使其返回0.如果xy为正,则最高有效位为0.否定它得到1并将其转移到返回1.它似乎不起作用。我这样做错了还是遗失了什么?

3 个答案:

答案 0 :(得分:3)

由于以下几个原因,您的方法不起作用:

  • 假设xy是有符号值,减法可能会溢出。根据C标准,这不仅会导致未定义的行为,而且在溢出包装的典型实现中,它会产生错误的结果。例如,如果xINT_MINy1,则x-y将产生INT_MAX,其未设置高位。

  • 如果xy是无符号值,那么x=UINT_MAXy=0就是您得到错误答案的示例。您必须对xy的值施加条件(例如,既没有高位设置),以便此测试有效。

归结为,为了通过测试“高位”执行比较,您需要比所比较的值中的位数多一位。在合理的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的第一位是x0的第一位是y那么你可以确定x> y )。