不用任何比较判断找出两个数中较大的数
【题目】
给定两个32位整数a和b,返回a和b中较大的。
【要求】
不用任何比较判断。
【解答】
这里有两种方法进行解决,两种方法原理都一样的,只是第二种是第一种的优化。
sign函数的功能是返回整数n的符号,正数和0返回1,负数返回0.flip函数的功能是做n的异或运算,n是1返回0,n是0返回1。
方法一:
我们不能直接比较,那么就用减法来判断,a - b值的符号,符号为正a大,符号为负b大。scA表示c的符号,scB表示c的相反的符号,scA是1返回a,scA是0返回B.但是有局限性,那就是a-b的值可能出现溢出,返回结果不正确。
方法二:
先比较a与b两个数的符号,符号不同difSab==1,sameSab==0;直接返回符号为正的那个数。
如果a为0或正,那么b为负(sa==1,sb==0),则返回a;
如果a为负,那么b为0或正(sa==0,sb==1),则返回b;
如果符号相同difSab==0,sameSab==1,这种情况下,a-b的值绝对不会溢出,那么就看c的符号。
如果c=a-b,为正返回a;
如果c=a-b,为负返回b;
代码如下:
public class CompleteTwoNum {
/**
* 异或运算
*/
public int flip(int n) {
return n ^ 1;
}
/**
* n是正数或0返回1 n是负数返回0
*/
public int sign(int n) {
return flip((n >> 31) & 1);
}
public int getMax1(int a, int b) {
int c = a - b;
int scA = sign(c);// 返回c的符号,正数和0是1,负数是0
int scB = flip(scA);// 返回c的符号的相反符号
return a * scA + b * scB;
}
/**
* 如果a、b的符号相同(+,+)、(-,-),difSab=0,returnA=sc;如果sc是1,返回a,否则返回b
* 如果a、b的符号不同(+,-)、(-,+),disSab=1,returnA=sa;如果sa是1,返回a,否则返回b
*/
public int getMax2(int a, int b) {
int c = a - b;
int sa = sign(a);// 返回a的符号
int sb = sign(b);// 返回b的符号
int sc = sign(c);// 返回c的符号
int difSab = sa ^ sb;
int sameSab = flip(difSab);
int returnA = difSab * sa + sameSab * sc;
int returnB = flip(returnA);
return a * returnA + b * returnB;
}
public static void main(String[] args) {
CompleteTwoNum twoNum = new CompleteTwoNum();
Scanner s = new Scanner(System.in);
int a = s.nextInt();
int b = s.nextInt();
System.out.println("方法一: a=" + a + " , b=" + b + " 大数是:"
+ twoNum.getMax1(a, b));
System.out.println("方法二: a=" + a + " , b=" + b + " 大数是:"
+ twoNum.getMax2(a, b));
// System.out.println(Integer.MAX_VALUE);// 最大整数2147483647
// System.out.println(Integer.MIN_VALUE);// -2147483648是32机器中所能表示的最小int。
}
}
运行结果如下:
123 456
方法一: a=123 , b=456 大数是:456
方法二: a=123 , b=456 大数是:456
方法一结果溢出的结果如下:
-2147483648 8
方法一: a=-2147483648 , b=8 大数是:-2147483648
方法二: a=-2147483648 , b=8 大数是:8