Java数据结构和算法:位运算
位運(yùn)算因?yàn)槭荂PU直接支持的操作指令,也是基于二進(jìn)制的操作,所以具有相當(dāng)高的效率,在一些場(chǎng)合,合理應(yīng)用位運(yùn)算將具有很高的性能。通常在一些加密算法,圖型算法中都會(huì)使用到位運(yùn)算。
移位運(yùn)算符
| << | 左移運(yùn)算符,將運(yùn)算符左邊的對(duì)象向左移動(dòng)運(yùn)算符右邊指定的位數(shù)(在低位補(bǔ)0) | x<<3 |
| >> | “有符號(hào)”右移運(yùn)算 符,將運(yùn)算符左邊的對(duì)象向右移動(dòng)運(yùn)算符右邊指定的位數(shù)。使用符號(hào)擴(kuò)展機(jī)制,也就是說(shuō),如果值為正,則在高位補(bǔ)0,如果值為負(fù),則在高位補(bǔ)1. | x>>3 |
| >>> | “無(wú)符號(hào)”右移運(yùn)算 符,將運(yùn)算符左邊的對(duì)象向右移動(dòng)運(yùn)算符右邊指定的位數(shù)。采用0擴(kuò)展機(jī)制,也就是說(shuō),無(wú)論值的正負(fù),都在高位補(bǔ)0. | x>>>3 |
對(duì)于java移位運(yùn)算的總結(jié)
對(duì)于左移運(yùn)算,每左移一個(gè)位,高階位都被移出(并且丟棄),并用0填充右邊。這意味著當(dāng)左移的運(yùn)算數(shù)是int 類型時(shí),每移動(dòng)1位,它的第31位就要被移出并且丟棄;當(dāng)左移的運(yùn)算數(shù)是long 類型時(shí),每移動(dòng)1位它的第63位就要被移出并且丟棄。
左移都可以使原來(lái)的操作數(shù)翻倍,程序員們經(jīng)常使用這個(gè)辦法來(lái)進(jìn)行快速的2 的乘法。但是你要小心,如果你將1移進(jìn)高階位(31或63位),那么該值將變?yōu)樨?fù)值。
在對(duì)byte 和short類型的值進(jìn)行移位運(yùn)算時(shí) , Java將自動(dòng)把這些類型擴(kuò)大為 int 型,而且,移位后的值也是int 型;如果左移不超過(guò)31位,原來(lái)對(duì)應(yīng)各位的值不會(huì)丟棄。但是,如果你對(duì)一個(gè)負(fù)的byte 或者short類型的值進(jìn)行移位運(yùn)算,它被擴(kuò)大為int 型后,它的符號(hào)也被擴(kuò)展,結(jié)果的高位就會(huì)被1填充。因此,為了得到正確的結(jié)果,你就要舍棄得到結(jié)果的高位。這樣做的最簡(jiǎn)單辦法是將移位運(yùn)算的結(jié)果再轉(zhuǎn)換成byte 型 。
每右移一次,就相當(dāng)于將該值除以2并且舍棄了余數(shù)。你可以利用這個(gè)特點(diǎn)將一個(gè)整數(shù)進(jìn)行快速的2的除法。當(dāng)然,你一定要確保你不會(huì)將該數(shù)原有的任何一位移出。
無(wú)符號(hào)右移(>>>)與右移的區(qū)別:
每一次右移,>>運(yùn)算符總是自動(dòng)地用它的先前最高位的內(nèi)容補(bǔ)它的最高位。這樣做保留了原值的符號(hào)
無(wú)符號(hào)移動(dòng)總是在高位(最左邊)補(bǔ)0。
與C、C++不同,Java中沒(méi)有無(wú)符號(hào)型整數(shù),而且明確規(guī)定了整型和浮點(diǎn)型數(shù)據(jù)所占的內(nèi)存字節(jié)數(shù),這樣就保證了安全性、魯棒性和平臺(tái)無(wú)關(guān)性。
roundUpToPowerOfTwo(int i)
獲取大于等于 某個(gè)整數(shù) 并且是 2 的冪數(shù)的整數(shù)
public static int roundUpToPowerOfTwo(int i) {i--; // If input is a power of two, shift its high-order bit right.// "Smear" the high-order bit all the way to the right.i |= i >>> 1;i |= i >>> 2;i |= i >>> 4;i |= i >>> 8;i |= i >>> 16;return i + 1; }可以看到這個(gè)算法進(jìn)行了 5 次移位操作,乍一看,一臉懵逼,這是在干嘛?
細(xì)細(xì)一想啊,我現(xiàn)在要獲取一個(gè)是 2 的冪數(shù)的整數(shù),那其二進(jìn)制的表現(xiàn)形式就是其最高位為1 ,低位全部為 0;或者其低位全部為 1,只需再對(duì)其加 1,即可變成 2 的倍數(shù)。
舉個(gè)例子:
1000 0000
0100 0000 // 無(wú)符號(hào)右移一位
1100 0000 // 上面兩個(gè)執(zhí)行或操作的結(jié)果
1100 0000
0011 0000 // 無(wú)符號(hào)右移二位
1111 0000 // 上面兩個(gè)執(zhí)行或操作的結(jié)果
1111 0000
0000 1111 // 無(wú)符號(hào)右移三位
1111 1111 // 上面兩個(gè)執(zhí)行或操作的結(jié)果
其實(shí)我們只需將我們的關(guān)注點(diǎn)放置其元素為1的最高位上,執(zhí)行右移操作,緊接著是或操作,最后的結(jié)果就是將高位的1,向后涂抹 (smear),全部變?yōu)?。
移位5次的原因在于 Java 中的整數(shù)是32位的,正好是2的 5次方。
算法剛開始的減一操作,則是為了防止剛開始傳入的數(shù)字便是 2 的冪數(shù)。用來(lái)保證最終的結(jié)果是大于等于傳入的參數(shù)的值。
總結(jié)
以上是生活随笔為你收集整理的Java数据结构和算法:位运算的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 详细介绍Java和C++区别
- 下一篇: Android进程保活招式大全