题目:已知两个整数a、b,a和b的值均没有出现溢出,而a + b有可能出现溢出,现在需要在防止溢出的情况下求a和b的平均值,该平均值取其实际值的向下取整。
思路:求两个数的平均值最常见的思路就是将两个数相加,然后除以2,但是此处两个数相加可能出现溢出,因此不能采用这种方法。可以考虑将a和b先分别除以2,再求和。并且要求该平均值是实际平均值的向下取整。比较简单的有两种解法:
1)通过求商运算和求余运算求解。
针对a和b,分布对2求商,并将得到的商相加avg1;在此基础上,将a和b分别对2取余,并将余数相加得到的结果对2求商得到avg2,最终得结果avg = avg1 + avg2。
2)通过位运算求解。
我们知道,对整数右移一位相当于对2求商,因此我们可以先将a和b分别右移一位,并将结果相加得到avg1;如果一个整数为偶数,那么该整数与1做与运算的结果为0,如果该整数位奇数,则该整数与1做与运算的结果为1,因此,我们可以将a和b分别对1做与运算,并将得到的结果相加后向右移一位得到avg2,最终的结果avg = avg1 + avg2。注意:位运算的优先级低于“+”运算符,记得加上括号。
以下给出两种方法的java代码:
// 用求商运算和求余运算
public int getAverageOfTwoInt_1(int a, int b){
int c = a / 2 + b / 2 + (a % 2 + b % 2) / 2;
return c;
}
//用位运算
public int getAverageOfTwoInt_2(int a, int b){
int c = (a >> 1) + (b >> 1) + (((a & 1) + (b & 1)) >> 1);
// 错误的写法:由于 a & 1 + b & 1 没有加括号区分,得到的结果与我们预想不一样。
// int c = (a >> 1) + (b >> 1) + ((a & 1 + b & 1) >> 1);
return c;
}