我們知道程式中的所有數在電腦記憶體中都是以二進位的形式儲存的,而位元運算就是直接對整數在記憶體中的二進位位元進行操作。例如,and運算本來就是邏輯運算符,但整數與整數之間也可以進行and運算。
位元運算主要有移位運算和邏輯運算。下面我們就分別來講講移位運算和邏輯運算。
移位運算:
左移:運算子為c670841d78f9007c8fb76ce16be96697>>,向右移動,右邊的捨棄掉,左邊補0。有符號右移:操作符為>>,向右移動,右邊的捨棄掉,左邊補的值取決於原來最高位,原來是1就補1,原來是0就補0,將二進位看做整數,右移1位相當於除以2。
例如:
int a = 4; // 100 a = a >> 2; // 001,等于1 a = a << 3 // 1000,变为8
邏輯運算有:
#位元與&:兩位都為1才為1
按位元或|:只要有一位為1,就為1
#位元取反~: 1變成0,0變成1
按位異或^ :相異為真,相同為假
例如:
int a = ...; a = a & 0x1 // 返回0或1,就是a最右边一位的值。 a = a | 0x1 //不管a原来最右边一位是什么,都将设为1
我們來看幾個簡單的應用場景:
場景一:判斷奇偶
分析:奇數都不是2的整數倍,轉換成二進位後最低位必然為1,偶數則相反。利用這個特性我們可以很容易的通過位運算判斷一個整數的奇偶性。
看程式碼:
int i = 1;// 二进制存储方式为00000000000000000000000000000001 int j = 5;// 二进制存储方式为00000000000000000000000000000101 int k = 6;// 二进制存储方式为00000000000000000000000000000110 if ((i & j) == 1) { System.out.println("j的最低位为1,为奇数"); } if ((i & k) == 0) { System.out.println("k的最低位为0,为偶数"); }
場景二:判斷一個正整數是不是2的整數次方
分析:我們先來看看常見的2的整數次冪的數:2、4、8、16,轉換成二進位依序為:10、100、1000、10000,發現規律了沒有?那就是除了首位是1,其他全是0。恰巧這些數減去1後等於他們依序按位取反的結果,例如8-1=7,二進制是111,可以透過8的二進制1000按位取反得到。而8&7=0,提取一下規律就是:
(n&(n-1))==0
符合這個規律的n就是2的整數次方了。
(學習影片分享:java影片教學)
場景三:簡單的集合處理
不廢話,直接看程式碼:
public class SimpleSet { public static final int A = 0x01;// 最后四位为0001 public static final int B = 0x02;// 最后四位为0010 public static final int C = 0x04;// 最后四位为0100 public static final int D = 0x08;// 最后四位为1000 private int set = 0x00;// 初始0000,空集合 public void add(int i) {// 将i对应位的值置为1,重复add不影响。默认传入值为ABCD之一,此处省去边界判断 set |= i; } public boolean contain(int i) {// 判断相应位置是否为1 return (set & i) == i; } public boolean remove(int i) {// 来不及不解释了快看代码 if (contain(i)) { set -= i; return true; } else { return false; } } }
測試一下:
public static void main(String[] args) { SimpleSet set = new SimpleSet(); System.out.println(set.contain(A)); set.add(B); System.out.println(set.contain(A)); System.out.println(set.contain(B)); set.add(A); set.add(C); System.out.println(set.contain(A)); set.remove(A); System.out.println(set.contain(A)); System.out.println(set.remove(A)); System.out.println(set.contain(C)); }
輸出為:
false false true true false false true
好的,沒有問題。
大家可能會覺得,上面的範例程式碼中的A、B、C、D有點類似枚舉,事實上jdk原始碼中的關於枚舉的集合類別EnumSet使用的就是類似的方案,當然比這個複雜得多,有興趣的可以去翻一下源碼,這個方案它有個名字,叫位向量。
順便提一句,java中int的包裝類別Integer裡面有很多靜態工具方提供位元運算操作,而且大都十分複雜,有興趣的可以去看看
結語:
位元運算是電腦最擅長的運算,jdk的原始碼中也大量使用了它,搞清楚它有助於我們更深入的理解計算機,也有助於我們寫出更優雅的程式碼。
相關推薦:java入門教學
#以上是java中的位元運算及應用場景介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!