方法一:首先我们来看看用函数怎么样实现这个题目?
#include <iostream>
using namespace std;
int MAX(int a,int b)
{
int d=a-b;
int flag=((unsigned int)d)>>31;
//此处将d转化为 unsigned int的目的是,相右移动时,低位移出,高位补零,无无符号数没有符号位的
//概念,所以只能补0.而有符号数,比如-7,它的符号位就是1
int array[]={a,b};
return array[flag];
}
int main()
{
cout<<MAX(1,2)<<endl;
cout<<MAX(5,2)<<endl;
cout<<MAX(3,100)<<endl;
return 0;
}
方法二:利用宏来实现,在GCC编译器下来实现
//将刚刚实现的程序进行优化一下
#include <iostream>
using namespace std;
int MAX(int a,int b)
{
int array[]={a,b};
return array[((unsigned int)(a-b))>>31];
}
int main()
{
cout<<MAX(1,2)<<endl;
cout<<MAX(5,2)<<endl;
cout<<MAX(3,100)<<endl;
return 0;
}
然后再将上面的程序写成宏的形式
在GCC编译器下,利用2个参数实现如下:
#include <iostream>
using namespace std;
#define MAX(a,b) ({int array[]={a,b};array[((unsigned int)(a-b))>>31];})
int main()
{
cout<<MAX(1,2)<<endl;
cout<<MAX(5,2)<<endl;
cout<<MAX(3,100)<<endl;
return 0;
}
注意:({})这样的语法是GCC编译器下特有的语法,与标准C/C++编译器下 ()是一样的,与逗号表达式类似。
比如:
标准C/C++编译器下的实现
int a=1;
int b=2;
int r=(a=1,b=2,a+b); // r=3
//GCC编译器的实现
int r=({int a=1;int b=2;a+b;});
#include <iostream>
using namespace std;
#define MAX(a,b,type) ({type array[]={a,b};array[((unsigned int)(a-b))>>31];})
int main()
{
float a=7.8;
float b=10.34;
cout<<MAX(a,b,float)<<endl;
//cout<<MAX(5,2,int)<<endl;
//cout<<MAX(3.22,100.12,double)<<endl;
return 0;
}
//将上述程序优化一下,可以支持任意的类型,不仅仅是int类型,也可以是其他的类型,比如float,double等。
进一步的深度思考有没有考虑过,a-b会发生溢出的现象呢?就比如下面的程序:
#include <iostream>
using namespace std;
#include <iostream>
using namespace std;
int MAX(int a,int b)
{
int d=a-b;
cout<<"d="<<d<<endl;//因为会发生溢出,所以此时 d=2147483647
int flag=((unsigned int)d)>>31;
int array[]={a,b};
return array[flag];
}
int main()
{
int a=-2;
int b=2147483647;//此时b表示的4字节有符号整数的最大值,2^31-1
cout<<MAX(a,b)<<endl;
return 0;
}
这个时候那么这个比较算法是不是出现问题呢?对,因为没有考虑到溢出的情况在里面。
#include <stdio.h>
int MAX(int a,int b)
{
//用来保存原始数据中的两个数
int array[]={a,b};
//用来保存两个数中的最大值,根据a,b的正负组合,一共有4种情况
int r[]=
{
array[((unsigned int)(a-b))>>31],//a,b都是正数的情况
//如果a<b,最高位一定为1,存入b ;如果a>b,最高位一定为0,存入a
a,//a正b负,a一定大于b
b,//a负b正,b一定大于a
array[((unsigned int)(a-b)>>31)] //a,b都是负数的情况
//如果a<b ,这最高位一定为1,存入b; 如果a>b,最高位一定为0,存入a
};
//判读a和b的正负组合属于那种情况
//int转化为unsigned int后,最高位就有2种情况,正数或者0:0,负数:1
//组合;同正 00,正负01,负正10,负负11,恰好是array的下标
unsigned x=(((unsigned int)(a))>>30)&2; //取a的最高位,作为下标右边的第2位
unsigned y=((unsigned int)(b))>>31; //取b的最高位,作为下标右边第1位
unsigned i=x|y; //合成a和b的最高位作为array的下标
return r[i];//取到相应情况的最大值
}
int main()
{
int a=-2;
int b=2147483647;//此时b表示的4字节有符号整数的最大值,2^31-1
printf("%d\n",MAX(a,b));
return 0;
}
与之相对应的宏为下面所示:这个宏可以适用于任何类型
#define MAX(a, b, type) ({type _ab_[] = {(a), (b)}; int _i_ = ((unsigned long long)((a)-(b))) >> 63; type _r_[] = {_ab_[_i_], (a), (b), _ab_[_i_]}; _r_[((((unsigned long long)(a)) >> 62)&2)|(((unsigned long long)(b)) >> 63)];})