17.Java位運算

17.Java位運算
轉載請保留原文鏈接: http://dashidan.com/article/java/basic/17.html

位運算是通過二進制計算的方式來改變數據.位運算表達式由操作數和位運算符組成,實現對整數類型的二進制數進行位運算.位運算符可以分爲邏輯運算符(包括~,&,|和^)及移位運算符(包括>>,

① Java進位方式

在Java語言中, 二進制數使用補碼錶示, 最高位爲符號位, 正數的符號位爲0, 負數爲1.

補碼的表示規則:

  • 正數的最高位爲0,其餘各位代表數值本身(二進制數).
  • 對於負數,通過對該數絕對值的補碼按位取反,再對整個數加1.

2進制

2進制即爲滿2進1. 第n位表示2^(n-1)(2的n-1次冪). 數據在計算機內存中以二進制的形式存儲.以int類型舉例, 佔4個字節共32位(1個字節佔8位). 數字100, int類型的二進制數:

    0000 0000 0000 0000 0110 0100

數字太長, 不便於理解.因此C,C++以及java中都沒有提供在代碼直接寫二進制數的方法.

8進制

8進制即爲滿8進1. 第n位表示8^(n-1)(8的n-1次冪). 一個數如果採用八進制, 必須在它前面加上一個數字0.

例:

package com.dashidan.lesson16;

/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇: 16. Java位運算
 */
public class Demo1 {
    public static void main(String[] args) {
        /** 10進制*/
        int a = 100;
        /** 8進制*/
        int b = 0100;
        System.out.println("a: " + a + " b: " + b);
    }
}

輸出:

a: 100 b: 64

用8進製表達時,不能少了最前邊的數字`0`.否則計算機會當成10進制處理.但用轉義字符表達時,不能加0.

16進制

16進制即爲滿16進1. 第n位表示16^(n-1)(16的n-1次冪). 10-15的數字分別以字母a到f表示, 不區分大小小. 16進制數必須以0x開頭.x不區分大小寫.

package com.dashidan.lesson16;

/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇: 16. Java位運算
 */
public class Demo1 {
    public static void main(String[] args) {
        /** 10進制*/
        int a = 100;
        /** 8進制*/
        int b = 0100;
        /** 16進制*/
        int c = 0x100;
        System.out.println("a: " + a + " b: " + b + " c: " + c);
    }
}

輸出:

a: 100 b: 64 c: 256

0x中的0是數字0,而不是字母O

真相只有一個

8進制和16進制只能用來表達無符號的正整數?

網上有資料這樣說, 但這個是錯誤的. 8進制和16進制同樣可以表示負數.

附帶真相的代碼:

package com.dashidan.lesson16;

/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇: 16. Java位運算
 */
public class Demo1 {
    public static void main(String[] args) {
        int d = -0100;
        int e = -0x100;
        System.out.println("d: " + d + " e: " + e);
    }
}
輸出: d: -64 e: -256

② 位運算邏輯運算符

位運算邏輯運算符包括: 與(&),非(~),或(|),異或(^).

  • &: 與. 當兩邊操作數的位同時爲1時, 結果爲1, 否則爲0.

例:

1100&1010=1000 

位運算判斷奇偶, 偶數的最低位是0,奇數的最低位是1.通過這個原理, 我們可以根據整數二進制最後一位與1比較, 判斷奇偶.

package com.dashidan.lesson16;

import java.util.Random;

/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇: 16. Java位運算
 * 位運算判斷奇偶
 */
public class Demo2 {
    public static void main(String[] args) {
        /** 隨機一個整數*/
        int a = new Random().nextInt();
        /** 判斷奇偶性*/
        String numStr = ((a & 1) == 1) ? "奇數" : "偶數";
        System.out.println("隨機數爲: " + a + " 是: " + numStr);
    }
}

輸出:

隨機數爲: 476218275 是: 奇數
  • |: 或. 當兩邊操作數的位有一邊爲1時,結果爲1,否則爲0.

例:

1100|1010=1110
  • ~: 按位取反. 0變1,1變0.

負數在內存中的表現是, 按位取反再加1.

  • ^: 按位異或. 參與運算的兩個值,如果兩個相應位相同,則結果爲0,否則爲1.

0異或任何數等於任何數, 1異或任何數等於任何數取反, 任何數異或自己等於把自己置0

即:

0^0=0
1^0=1 
0^1=1 
1^1=0

不用臨時變量交換兩個數

通過按位異或運算,可以實現兩個值的交換,而不必使用臨時變量. 這個很酷.

例:

交換兩個整數a,b的值,可通過下列語句實現:

package com.dashidan.lesson16;

/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇: 16. Java位運算
 * 不用臨時變量交換兩個數
 */
public class Demo3 {
    public static void main(String[] args) {
        /** 數a兩次異或同一個數b(a=a^b^b)仍然爲原值.*/
        int a = 100;
        int b = 666;

        a = a ^ b;
        b = b ^ a;
        a = a ^ b;

        System.out.println("a: " + a + " b " + b);
    }
}

輸出:

a: 666 b 100

數a兩次異或同一個數b(a=a^b^b)仍然爲原值.

③ 移位運算符

java移位運算符包括:

  • <<:左移位
  • >>:帶符號右移
  • >>>:無符號右移

1.左移位運算符(<<)

使指定值的所有位都向左移規定的次數, 丟棄最高位, 在低位補0. 在數字沒有溢出的前提下,對於正數和負數, 左移一位都相當於乘以2的1次方, 左移n位就相當於乘以2的n次方.

如果位數超過了該類型的最大位數, 該值將變爲負值.

格式:

value << num 

num 指定要移位值value 移動的位數.

如果移動的位數超過了該類型的最大位數,那麼編譯器會對移動的位數取模.

如對int型移動33位,實際上只移動了33%32=1位.

計算過程:
4<<2爲例

    1.把3轉換爲二進制數字0000 0000 0000 0000 0000 0000 0000 0100, 
    2.把該數字高位(左側)的兩個零移出,其他的數字都朝左平移2位, 
    3.在低位(右側)的兩個空位補零.得到的最終結果是0000 0000 0000 0000 0000 0000 0001 0000, 
    轉換爲十進制是12. 
package com.dashidan.lesson16;

/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇: 16. Java位運算
 * 移位運算符
 */
public class Demo4 {
    public static void main(String[] args) {
        int a = 4;
        int b = a << 2;
        System.out.println("a: " + a + " b: " + b);
    }
}

輸出:

a: 4 b: 16

2.有符號右移位運算符>>

使指定值的所有位都向右移規定的次數.正數在高位插入0,負數則在高位插入1. 右移一位相當於除2, 右移n位相當於除以2的n次方.

格式如下:

value >> num 

num 指定要移位值value 移動的位數.

package com.dashidan.lesson16;

/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇: 16. Java位運算
 * 移位運算符
 */
public class Demo4 {
    public static void main(String[] args) {
        int a = 4;
        int b = a << 2;
        System.out.println("a: " + a + " b: " + b);

        int c = 1000;
        int d = c >> 2;
        System.out.println("c: " + a + " d: " + d);
    }
}

輸出:

c: 1000 d: 250

3.”無符號”右移位運算符(>>>).

忽略了符號位擴展,無論正負,都在高位插入0.

格式如下:

value >>> num 

num指定要移位值value移動的位數.

package com.dashidan.lesson16;

/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇: 16. Java位運算
 * 移位運算符
 */
public class Demo4 {
    public static void main(String[] args) {
        int e = -1;
        int f = e >>> 2;
        System.out.println("e: " + e + " f: " + f);
    }
}

輸出:

e: -1 f: 1073741823

只是對32位和64位的值有意義.這一運算符是C或C++沒有的.

char,byte或者short移位

在移位前,它們會自動轉換成一個int. 移位操作符右端的那個數(轉化成二進制)的5個低位纔會用到, 即x

④ 位運算符的優先級

~的優先級最高,其次是<<,>>和>>>,再次是&,然後是^,優先級最低的是|.

⑤ 相關文章

Java從入門到精通

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章