前言
今天在水群的過程中看到有位群員談論到這個話題,是他找工作過程中某家公司的面試題(到底是哪家公司才會出這種沒營養的題目刁難别人),有點興趣,就開始寫了。
開搞
想了一下,其實就是題目怪了一點,難度其實并不高。這個題目讓我想起了前兩年看到的題目,隻給你加法,怎麼計算加減乘除(都說了到底是哪家公司才會出這種沒營養的題目)。相比起來,這題好歹是考了計算機中的加法器,而本文主題中談論的題目則真的是毫無營養。
思路其實很明顯,位運算,這類題目一般都是要用位運算的。這裡需要使用到無符号右移。
首先,既然不允許直接比較,那我就相減嘛,a-b結果是0就是相等,結果是負數就是a小,結果是正數那就是a大。
當然這裡是不能直接比較結果的正負的, 這樣依然不符合提議,怎麼辦呢。
一切的運算在計算機中都是二進制,數字也是用二進制表示的,而二進制表示數字的時候,最高位是代表符号位,1是負數,0是正數,傳統的int最高32位。是以我們隻需要判斷第32位的結果是0還是1就能判斷誰大誰小。直接判斷第32位肯定不現實,這裡就需要使用到無符号右移運算符“>>>”。舉個簡單的例子,下面這串二進制隻需要無符号右移31位,就可以得到最高位的值
1000 0010 1101 0100 1101 0001 0010 0011
無符号右移31位後
0000 0000 0000 0000 0000 0000 0000 0001
結果顯而易見,最高位降到了最低位,其餘位全部變成了0,是以,隻要結果是負數,那麼進行 >>>31 之後的結果轉為十進制就是1,否則為0。
int a = 10;
int b = 12;
int index = (a - b) >>> 31;
這樣,我們隻需要判斷index即可。
那麼問題來了,題目要求是不允許判斷,該怎麼辦呢?其實這裡可以使用數組,下标為0的地方輸出a>=b,為1的地方輸出a<b。
完整代碼:
public void test() {
int a = 10;
int b = 12;
int index = (a - b) >>> 31;
String[] arr = {"a>=b", "a<b"};
System.out.println(arr[index]);
}
至此,已經基本可以判斷a和b的大小了。但是到這裡可以發現,a=b和a>b的情況無法分離,這裡我們可以繼續思考。
當a=b時,a-b=0,那麼數組0下标位置是否可以直接放a=b?接着,我們把上面的index+1,結果就變成了:1下标位置是大于等于,2下标位置是小于。其中,等于的情況已經在0下标位置,是以1下标位置的結果就是a>b了。
String[] arr = {"a=b", "a>b", "a<b"};
分析到這裡,思路已經很清晰,首先我們計算a-b,直接作為下标取arr中的資料,如果報錯了,說明不是0、1、2的情況,那麼就繼續按照上面的思路進行位運算,取出1和2下标的值 。
public void test() {
int a = 13;
int b = 12;
int diff = a - b;
String[] arr = {"a=b", "a>b", "a<b"};
try {
System.out.println(arr[diff]);
} catch (ArrayIndexOutOfBoundsException e) {
int index = diff >>> 31;
System.out.println(arr[index + 1]);
}
}
到了這裡,程式還存在一個bug,當a-b=2時,該程式的判斷結果是有問題的,是以,我們需要把計算結果為2的情況給排除,做法很簡單,把diff這個變量進行有符号左移2位的操作即可(如果隻移1位,當diff為1時,計算結果是2,不符合題意)。左移2位之後的結果絕對值肯定比2要大,是以也就杜絕了出現下标為2的情況。
最終代碼。
public void test() {
int a = 14;
int b = 12;
int diff = (a - b) << 2;
String[] arr = {"a=b", "a>b", "a<b"};
try {
System.out.println(arr[diff]);
} catch (ArrayIndexOutOfBoundsException e) {
int index = diff >>> 31;
System.out.println(arr[index + 1]);
}
}