轉載請保留原文鏈接: 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
④ 位運算符的優先級
~的優先級最高,其次是<<,>>和>>>,再次是&,然後是^,優先級最低的是|.