网上有较多的帖子讨论一些面试的题目,其中有一道就是“定义一个宏,比较两个数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; }