网上有较多的帖子讨论一些面试的题目,其中有一道就是“定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句”
从原理上将,一个int整形变量,最高位是正负位,只要知道两者差值最高位是正还是负,差是零还是非零就能知道两个数的大小。
这里简单整理了网络上给出的较多答案,并做了简单的验证。
验证一:
#define ZHENG(i) ((i >> 31) == 0)
#define FU(i) ((i >> 31) != 0)
#define COMPARE_1(a, b) ((ZHENG(a) && FU(b)) \
|| (((ZHENG(a) && ZHENG(b)) \
|| (FU(a) && FU(b))) \
&& ((((a) - (b)) >> 31) == 0)))
验证二:
#define COMPARE_2(a, b) (((((long)((b)-(a)))&0x80000000)?-1:0)|((((long)((a)-(b)))&0x80000000)?1:0))
验证三:
#define COMPARE_3(a, b) ( ( ( (int)( b ) )-( (int)( a ) ) ) >> ( sizeof( int )*8-1 ) & 0x1 )
验证四:
#define COMPARE_4(a, b) (((b) - (a) & (0x1 << 31)) >> 31)
验证五:
#define MAX(a, b) (((a)-(b)) & 0x80000000 ) ? (b) : (a)
验证六:
#define new_big_than(a, b) !!( ((a) < 0 || (b) < 0) ? (((b) - (a) & (0x1 << 31)) >> 31) : (( (b) == 0)? (a): (a)/(b)) )
验证七:
#define old_big_than(a, b) !!(((b) - (a) & (0x1 << 31)) >> 31)
验证八:
#define big_than(a, b) (b - a)?(((unsigned long)(((b) - (a)) / abs((b) - (a))) & (0x1 << 31)) >> 31):0
只要根据上面的原理,就能分析出这个宏究竟该如何写。这里先给出验证的结果:
验证代码:
#include <stdio.h>
#define ZHENG(i) ((i >> 31) == 0)
#define FU(i) ((i >> 31) != 0)
#define COMPARE_1(a, b) ((ZHENG(a) && FU(b)) \
|| (((ZHENG(a) && ZHENG(b)) \
|| (FU(a) && FU(b))) \
&& ((((a) - (b)) >> 31) == 0)))
#define COMPARE_2(a, b) (((((long)((b)-(a)))&0x80000000)?-1:0)|((((long)((a)-(b)))&0x80000000)?1:0))
#define COMPARE_3(a, b) ( ( ( (int)( b ) )-( (int)( a ) ) ) >> ( sizeof( int )*8-1 ) & 0x1 )
#define COMPARE_4(a, b) (((b) - (a) & (0x1 << 31)) >> 31)
#define MAX(a, b) (((a)-(b)) & 0x80000000 ) ? (b) : (a)
#define new_big_than(a, b) !!( ((a) < 0 || (b) < 0) ? (((b) - (a) & (0x1 << 31)) >> 31) : (( (b) == 0)? (a): (a)/(b)) )
#define old_big_than(a, b) !!(((b) - (a) & (0x1 << 31)) >> 31)
#define big_than(a, b) (b - a)?(((unsigned long)(((b) - (a)) / abs((b) - (a))) & (0x1 << 31)) >> 31):0
int main(int argc, char **argv)
{
int iInput = 1;
char buffer1[64];
char buffer2[64];
int iVal1, iVal2;
while(iInput)
{
printf("Please input your first and second value: (\"exit\" to quit the program)\r\n");
scanf("%s", buffer1);
if (0 == strcmp("exit", buffer1))
{
iInput = 0;
break;
}
scanf("%s", buffer2);
if (0 == strcmp("exit", buffer2))
{
iInput = 0;
break;
}
iVal1 = atoi(buffer1);
iVal2 = atoi(buffer2);
printf("==============================\r\n");
printf("%d > %d? test result:\r\n", iVal1, iVal2);
printf("COMPARE_1(%d, %d) = %d\r\n", iVal1, iVal2, COMPARE_1(iVal1, iVal2));
printf("COMPARE_2(%d, %d) = %d\r\n", iVal1, iVal2, COMPARE_2(iVal1, iVal2));
printf("COMPARE_3(%d, %d) = %d\r\n", iVal1, iVal2, COMPARE_3(iVal1, iVal2));
printf("COMPARE_4(%d, %d) = %d\r\n", iVal1, iVal2, COMPARE_4(iVal1, iVal2));
printf("MAX(%d, %d) = %d\r\n", iVal1, iVal2, MAX(iVal1, iVal2));
printf("big_than(%d, %d) = %d\r\n", iVal1, iVal2, big_than(iVal1, iVal2));
printf("old_big_than(%d, %d) = %d\r\n", iVal1, iVal2, old_big_than(iVal1, iVal2));
printf("new_big_than(%d, %d) = %d\r\n", iVal1, iVal2, new_big_than(iVal1, iVal2));
printf("++++++++++++++++++++++++++++++\r\n");
printf("%d > %d? test result:\r\n", iVal2, iVal1);
printf("COMPARE_1(%d, %d) = %d\r\n", iVal2, iVal1, COMPARE_1(iVal2, iVal1));
printf("COMPARE_2(%d, %d) = %d\r\n", iVal2, iVal1, COMPARE_2(iVal2, iVal1));
printf("COMPARE_3(%d, %d) = %d\r\n", iVal2, iVal1, COMPARE_3(iVal2, iVal1));
printf("COMPARE_4(%d, %d) = %d\r\n", iVal2, iVal1, COMPARE_4(iVal2, iVal1));
printf("MAX(%d, %d) = %d\r\n", iVal2, iVal1, MAX(iVal2, iVal1));
printf("big_than(%d, %d) = %d\r\n", iVal2, iVal1, big_than(iVal2, iVal1));
printf("old_big_than(%d, %d) = %d\r\n", iVal2, iVal1, old_big_than(iVal2, iVal1));
printf("new_big_than(%d, %d) = %d\r\n", iVal2, iVal1, new_big_than(iVal2, iVal1));
printf("==============================\r\n");
}
printf("Exit!\r\n");
return 0;
}