Day9-29.Shift operators

移位操作符

移位操作符操作的運算對象也是二進制的

移位操作符只可用來處理整數類型(基本類型的一種)。

左移位操作符(<<)能按照操作符右側制定的位數將操作符左邊的操作數向左移動(在低位補0)。

“有符號”右移位操作符(>>)則按照操作符右側制定的位數將操作符左邊的操作數向右移動。

“有符號”右移位操作符使用“符號擴展”:若符號爲正,則在高位插入0;若符號位負,則在高位插入1.

Java中增加了一種“無符號”右移位操作符(>>>),它使用“零擴展”:無論正負,都在高位插入0.

這一操作符是C或C++中所沒有的。

如果對char、byte或者short類型的數值進行移位處理,name在移位進行之前,它們會被轉換成int類型,

並且得到的結果也是一個int類型的值。只有數值有段的低5位纔有用。

這樣可防止我們移位超過int型值所具有的位數。(因爲2的5次方位32,而int型值只有32位。)

若對一個long類型的數值進行處理,最後得到的結果也是long。

此時只會用到數值右端的低6位,以防止移位超過long型數值具有的位數。

“移位”可與“等號”(<<=或>>=或>>>=)組合使用。

此時,操作符左邊的值會移動由右邊的值指定的位數,再將得到的結果賦給左邊的變量。

但在進行“無符號”右移位結合賦值操作時,可能會遇到一個問題:如果對byte或short值進行這樣的移位運算,

得到的可能不是正確的結果。

它們會先被轉換成int類型,再進行右移操作,然後被截斷,賦值給原來的類型。在這種情況下可能得到-1的結果。

下面這個例子演示了這種情況:

//: operators/URShift.java
// Test of unsigned right shift.
import static net.mindview.util.Print.*;

public class URShift {
  public static void main(String[] args) {
    int i = -1;
    print(Integer.toBinaryString(i));
    i >>>= 10;
    print(Integer.toBinaryString(i));
    long l = -1;
    print(Long.toBinaryString(l));
    l >>>= 10;
    print(Long.toBinaryString(l));
    short s = -1;
    print(Integer.toBinaryString(s));
    s >>>= 10;
    print(Integer.toBinaryString(s));
    byte b = -1;
    print(Integer.toBinaryString(b));
    b >>>= 10;
    print(Integer.toBinaryString(b));
    b = -1;
    print(Integer.toBinaryString(b));
    print(Integer.toBinaryString(b>>>10));
  }
} /* Output:
11111111111111111111111111111111
1111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
1111111111111111111111
*///:~


在最後一個移位運算中,結果沒有賦給b,而是直接打印出來,所以其結果是正確的。

下面這個例子向大家闡釋瞭如何應用涉及“按位”操作的所有操作符:

//: operators/BitManipulation.java
// Using the bitwise operators.
import java.util.*;
import static net.mindview.util.Print.*;

public class BitManipulation {
  public static void main(String[] args) {
    Random rand = new Random(47);
    int i = rand.nextInt();
    int j = rand.nextInt();
    printBinaryInt("-1", -1);
    printBinaryInt("+1", +1);
    int maxpos = 2147483647;
    printBinaryInt("maxpos", maxpos);
    int maxneg = -2147483648;
    printBinaryInt("maxneg", maxneg);
    printBinaryInt("i", i);
    printBinaryInt("~i", ~i);
    printBinaryInt("-i", -i);
    printBinaryInt("j", j);
    printBinaryInt("i & j", i & j);
    printBinaryInt("i | j", i | j);
    printBinaryInt("i ^ j", i ^ j);
    printBinaryInt("i << 5", i << 5);
    printBinaryInt("i >> 5", i >> 5);
    printBinaryInt("(~i) >> 5", (~i) >> 5);
    printBinaryInt("i >>> 5", i >>> 5);
    printBinaryInt("(~i) >>> 5", (~i) >>> 5);

    long l = rand.nextLong();
    long m = rand.nextLong();
    printBinaryLong("-1L", -1L);
    printBinaryLong("+1L", +1L);
    long ll = 9223372036854775807L;
    printBinaryLong("maxpos", ll);
    long lln = -9223372036854775808L;
    printBinaryLong("maxneg", lln);
    printBinaryLong("l", l);
    printBinaryLong("~l", ~l);
    printBinaryLong("-l", -l);
    printBinaryLong("m", m);
    printBinaryLong("l & m", l & m);
    printBinaryLong("l | m", l | m);
    printBinaryLong("l ^ m", l ^ m);
    printBinaryLong("l << 5", l << 5);
    printBinaryLong("l >> 5", l >> 5);
    printBinaryLong("(~l) >> 5", (~l) >> 5);
    printBinaryLong("l >>> 5", l >>> 5);
    printBinaryLong("(~l) >>> 5", (~l) >>> 5);
  }
  static void printBinaryInt(String s, int i) {
    print(s + ", int: " + i + ", binary:\n   " +
      Integer.toBinaryString(i));
  }
  static void printBinaryLong(String s, long l) {
    print(s + ", long: " + l + ", binary:\n    " +
      Long.toBinaryString(l));
  }
} /* Output:
-1, int: -1, binary:
   11111111111111111111111111111111
+1, int: 1, binary:
   1
maxpos, int: 2147483647, binary:
   111 1111 1111 1111 1111 1111 1111 1111
maxneg, int: -2147483648, binary:
   1000 0000 0000 0000 0000 0000 0000 0000
i, int: -1172028779, binary:
   1011 1010 0010 0100 0100 0010 1001 0101
~i, int: 1172028778, binary:
   100 0101 1101 1011 1011 1101 0110 1010
-i, int: 1172028779, binary:
   100 0101 1101 1011 1011 1101 0110 1011
j, int: 1717241110, binary:
   110 0110 0101 1011 0000 0101 0001 0110
i & j, int: 570425364, binary:
   10 0010 0000 0000 0000 0000 0001 0100
i | j, int: -25213033, binary:
   1111 1110 0111 1111 0100 0111 1001 0111
i ^ j, int: -595638397, binary:
   1101 1100 0111 1111 0100 0111 1000 0011
i << 5, int: 1149784736, binary:
   100 0100 1000 1000 0101 0010 1010 0000
i >> 5, int: -36625900, binary:
   1111 1101 1101 0001 0010 0010 0001 0100
(~i) >> 5, int: 36625899, binary:
   10 0010 1110 1101 1101 1110 1011
i >>> 5, int: 97591828, binary:
   1011 101 0001 0010 0010 0001 0100
(~i) >>> 5, int: 36625899, binary:
   10 0010 1110 1101 1101 1110 1011
...
*///:~



程序末尾調用了兩個方法:printBinaryInt()和printBinaryLong().

它們分別接受int或long型的參數,並用二進制格式輸出,同時附有簡要的說明文字。

上面的例子還展示了對int和long的所有按位操作符的作用,還展示了int和long的最大值、最小值、+1和-1值,

以及它們的二進制形式,以使大家瞭解它們在機器中的具體形式。

注意最高位表示符號:0爲正,1爲負。

關於int部分的輸出正如上面所示。

數字的二進制表示形式成爲“有符號的二進制補碼”。

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