天天看點

不使用比較運算符如何比較兩個數的大小前言開搞

前言

今天在水群的過程中看到有位群員談論到這個話題,是他找工作過程中某家公司的面試題(到底是哪家公司才會出這種沒營養的題目刁難别人),有點興趣,就開始寫了。

開搞

想了一下,其實就是題目怪了一點,難度其實并不高。這個題目讓我想起了前兩年看到的題目,隻給你加法,怎麼計算加減乘除(都說了到底是哪家公司才會出這種沒營養的題目)。相比起來,這題好歹是考了計算機中的加法器,而本文主題中談論的題目則真的是毫無營養。

思路其實很明顯,位運算,這類題目一般都是要用位運算的。這裡需要使用到無符号右移。

首先,既然不允許直接比較,那我就相減嘛,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]);
    }
}
           

最後還是要吐槽一句,沒事别出這種沒營養的面試題刁難人家啦!