您好,登錄后才能下訂單哦!
很多人認(rèn)為位運算在實際開發(fā)過程中并沒什么用,學(xué)習(xí)位運算也只是為了應(yīng)付面試。這種想法是錯誤的,接下來我們就通過幾篇連載文章介紹一下位運算在實際開發(fā)過程中的幾個經(jīng)典應(yīng)用實例。如果對位運算規(guī)則掌握還不是很熟練,可以先閱讀《Java千問:Java語言位運算符詳解》。這篇文章不僅詳細(xì)講解了Java位運算的基本規(guī)則和一些常用的運算定律,同時還在文中提到了一些常用的位運算實際應(yīng)用,比如可以用位運算操作的方式快速把某個變量所在的內(nèi)存單元清零,或者位運算的方式實現(xiàn)某個變量快速倍增等等。但文中所這提到的這幾個實際應(yīng)用比較簡單,本次連載文章將為大家講述的是更加復(fù)雜和實際的應(yīng)用經(jīng)典案例。此外,為獲得更好的閱讀效果,請各位讀者在讀本文之前先熟練掌握”補碼”的計算規(guī)則。
按照傳統(tǒng)的思路,判斷一個整數(shù)的奇偶性是通過用這個數(shù)與2求模,看運算結(jié)果是否為0。學(xué)了位運算符以后,我們可以換一種思路來考慮問題。我們知道:Java語言中,所有數(shù)字存儲在內(nèi)存中,都要先轉(zhuǎn)換成補碼的形式。任何一個偶數(shù)用補碼表示出來后,它的最后一個二進(jìn)制位都是0,而奇數(shù)補碼的最后一個二進(jìn)制位都是1。所以,我們可以通過判斷這個整數(shù)的補碼的最后一位二進(jìn)制數(shù)是0還是1,來判斷這個數(shù)是偶數(shù)還是奇數(shù)。判斷的方法就是用這個數(shù)與1進(jìn)行按位與的操作,如果結(jié)果為0,那么這個數(shù)就是偶數(shù),否則就是奇數(shù)。如果大家不理解這個算法的原理,請看下圖:
為了方便表述,我們把要判斷奇偶性的數(shù)字稱為a。圖中,以橫線為界,分別展示了a為偶數(shù)和奇數(shù)的情況下,與數(shù)字1進(jìn)行按位與操作的結(jié)果。其中,上面的二進(jìn)制串是a的補碼,下面二進(jìn)制串是數(shù)字1的補碼??梢钥吹?,數(shù)字1被轉(zhuǎn)換成補碼之后,總共有32位,其中前31位都是0,最后1位的值是1。這就導(dǎo)致a補碼的前31位無論是0還是1,與數(shù)字1的補碼進(jìn)行按位與運算,運算結(jié)果的前31位都只能是0,決定最終運算結(jié)果的就只有a補碼最右邊的那個二進(jìn)制位。如果最右邊那一位是0,那么a就是偶數(shù),a與1按位與運算的最終結(jié)果是數(shù)字0。反過來,如果最右邊那一位是1,那么a就是奇數(shù),a與1按位與運算的最終結(jié)果是數(shù)字1。因此我們只要看一下a與數(shù)字1進(jìn)行按位與運算的結(jié)果就知道a的奇偶性了。具體的程序?qū)崿F(xiàn)如下:
常規(guī)算法求絕對值的思路是:首先判斷一個數(shù)a是否>=0,如果a>=0,則返回a本身,否則返回a的相反數(shù)。這個過程包含判斷和選擇兩個步驟。如果使用位運算符來實現(xiàn)求絕對值,可以省略掉判斷的步驟,直接返回運算結(jié)果。下面來講解一下使用位運算符求絕對值的基本原理。我們知道:任何一個二進(jìn)制位上的數(shù),與0進(jìn)行異或運算,運算的結(jié)果都與這個二進(jìn)制位上的數(shù)相同。把這個結(jié)論擴展一下,從原來某個數(shù)的單獨的一個二進(jìn)制位擴展到這個數(shù)字本身,可以得出另外兩個結(jié)論,第一個結(jié)論:任何一個整數(shù)與0進(jìn)行異或運算后依然保持不變。如果小伙伴不理解的話,請看下圖,我們以數(shù)字5作為例子分析講解:
另一個結(jié)論:任何一個整數(shù)與-1進(jìn)行異或運算后再加上1,得到的結(jié)果就是這個數(shù)的相反數(shù)。如果不理解的話,還是看下圖,仍然是以數(shù)字5分析講解:
以上兩個結(jié)論中,第一個結(jié)論比較容易理解。我們簡單的解釋一下第二個結(jié)論的原理。第二個結(jié)論能夠成立的關(guān)鍵就在于,數(shù)字-1用補碼的形式表示出來,恰好是一個32位全為1的二進(jìn)制串。這個二進(jìn)制串與任何一個其他二進(jìn)制串進(jìn)行按位異或運算,都可以達(dá)到”取反”的效果,而按照補碼的計算規(guī)則,一個正數(shù)按位取反后再加1,得到的就是它相反數(shù)。比如圖中的數(shù)字5,按位取反之后,再加1得到的就是-5。
至此,我們已經(jīng)知道怎樣通過位運算的方式獲得一個數(shù)的相反數(shù)了。在《Java千問:Java語言位運算符詳解》一文中還講過:int類型的正數(shù)經(jīng)過帶符號右移31位之后,得到的必然是0,而負(fù)數(shù)經(jīng)過帶符號右移31位得到的是-1。我們就可以通過右移所得到的這個0或者-1,判斷出這個數(shù)是正數(shù)還是負(fù)數(shù)。知道數(shù)字的正負(fù)屬性,然后再用位運算的方式得到這個數(shù)本身或者是它的相反數(shù),就能求出這個數(shù)的絕對值。按照這個思路,我們就可以來編寫求絕對值的程序了,程序如下:
示例程序中的變量a是int型,如果改為long型,對a帶符號右移63位也可有相同的運算效果。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。