平时我们都是使用了比较运算符和条件判断, 来进行数字大小的比较, 但是有一些比较巧妙的方法, 也可以比较大小.
查了一些资料, 之后, 发现了三种思路, 设两个数为a和b
- a - b的结果, 进行移位, 取符号位, 0说明结果是正数, a > b, 1说明结果是负数, a < b
- (a+b)/2 + |(a-b)/2| 或者 (a+b)/2 - |(a-b)/2| , 前者可以取得较大的值, 后者取得较小的值, 很容易数学上证明
- 分配一个长度为a的数组array[a], 判断array[b]是否越界, 越界在java中会抛出异常
下面是用java实现的上述三种方法
第一种的代码实现
/**
* 比较符号位 0表示a>b, 1表示a<b
* @param a
* @param b
* @return
*/
public static int compare(int a, int b) {
// >> 带符号的右移, >>> 无符号的右移
// return (((a - b) & 0x80000000) >> 31); // 判断符号位, a<b时为-1, 因为>>是带符号的右移, 保留了原来结果的符号位
return (((a - b) & 0x80000000) >>> 31); // 判断符号位
}
第二种
/**
* 返回a和b中较大的数
* @param a
* @param b
* @return
*/
public static int compare(int a, int b) {
double x = (double)a;
double y = (double)b;
return (int)((x+y)/2 + Math.abs((x-y)/2)); // 判断符号位
}
/**
* 返回a和b中较小的数
* @param a
* @param b
* @return
*/
public static int compare(int a, int b) {
double x = (double)a;
double y = (double)b;
return (int)((x+y)/2 - Math.abs((x-y)/2)); // 判断符号位
}
第三种
/**
* 通过数组越界来判断
* @param a
* @param b
* @return
*/
public static int compare(int a, int b) {
int[] array = new int[a];
try {
array[b] = 0; // b>a的话, 会越界, 报异常
} catch (ArrayIndexOutOfBoundsException e) {
return b;
}
return a;
}
三种方式的实现方法都很简单
小结
第一种可能是最差的一种, 只获得了一个谁大谁小的信息, 还需要用条件判断来返回最大最小值, 思路是好, 感觉不是特别好用.
第二种数学方法还是比较好的, 可以取得最大最小值, 而且很简单, 第三种方法很巧妙, 也可以获得最大最小值.
问题的延伸
最近看到这样一个问题
现给有一区间: $start - $end
给定一变量: $param
if $param < $start 则返回$param = $start
if $param > $end 则返回$param = $end
不用if else, 三元 等逻辑运算符
实现此算法
这个问题, 肯定需要不用条件和比较来比较两个数的大小,
/**
* 现给有一区间: $start - $end
* 一变量: $param
* if $param < $start 则返回$param = $start
* if $param > $end 则返回$param = $end
* 不用if else, 三元 等逻辑运算符
* 实现此算法
*/
public static int compare(int param, int start, int end) {
int[] array = new int[param];
try {
array[start] = 0; // param < start 越界异常
} catch (ArrayIndexOutOfBoundsException e) {
param = start;
}
try {
array[end] = 0; // param > end 没有越界异常
param = end;
} catch (ArrayIndexOutOfBoundsException e) {
}
return param;
}
public static int compare(int param, int start, int end) {
double p = (double) param;
double s = (double) start;
double e = (double) end;
// p < s 返回较大值
p = (p+s)/2 + Math.abs((p-s)/2);
// p > e 返回较小值
p = (p+e)/2 - Math.abs((p-e)/2);
// s < p < e 返回p
return (int)p;
}
这种问题可能会在笔试或面试的时候遇到, 平时还是要多积累, 多思考.
由于笔者水平有限, 如果错漏, 欢迎指正!
参考资料:
- 飝兒, 不用IF比较两数大小, 原文地址: http://www.haogongju.net/art/867439