平时我们都是使用了比较运算符和条件判断, 来进行数字大小的比较, 但是有一些比较巧妙的方法, 也可以比较大小.
查了一些资料, 之后, 发现了三种思路, 设两个数为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