位運算的思考題
1)請看下面的代碼段,回答a,b,c,d,e結果是多少?
public static void main(String[] args) {
int a=1>>2;//1向右位移2位
int b=-1>>2; // -向右位移兩位,算術右移
int c=1<<2;// 1向左位移2位,算術左移
int d=-1<<2;-1向左位移兩位
int e=3>>>2; // 無符號右移
//a,b,c,d,e結果是多少
System.out.println("a="+a);
System.out.println("b="+b);
System.out.println("C="+c);
System.out.println("d="+d);
System.out.println("e="+e);
}
運算符的優先級
在Java中,下邊的表達式運算的結果是:(位操作)。
~2=? // 按位取反操作
2&3=?// 2按位與3
2|3=?// 2按位或3
~-5=?// 按位取反
13&7=? // 13按位與7
5|4=?// 5按位或4
-3^3=?// -3按位異或3
二進制在運算中的說明
1.二進制是逢2進位的進位制,0、1是基本算符。
2.現代的電子計算機技術全部采用的是二進制,因為它只使用0、1兩個數字符號,非常簡單方便,易于用電子方式實現。計算機內部處理的信息,都是采用二進制數來表示的。二進制(Binary)數用0和1兩個數字及其組合來表示任何數。進位規則是"逢2進1",數字1在不同的位上代表不同的值,按從右至左的次序,這個值以二倍遞增。
原碼、反碼、補碼
對于有符號的而言:
1.二進制的最高位是符號位:0表示正數,1表示負數(口訣: 0旋轉90度還為0,1旋轉90度為負號“-”)
2.正數的原碼,反碼,補碼都一樣(三碼合一)
3.負數的反碼=它的原碼符號位不變,其它位取反(0->1,1->0)
4·負數的補碼=它的反碼+1,負數的反碼=負數的補碼-1
5.0的反碼,補碼都是0
6.java沒有無符號數,換言之,java中的數都是有符號的
7.在計算機運算的時候,都是以補碼的方式來運算的.
8,當我們看運算結果的時候,要看他的原碼
位運算符
位運算符Java中有7個位運算(&、|、^、~、>>、<<和>>>)
分別是按位與&、按位或|、按位異或^、按位取反~,它們的運算規則是:
按位與&:兩位全為1,結果為1,否則為0.
按位或|:兩位有一個為1,結果為1,否則為0
按位異或^:兩位一個為0,一個為1,結果為1,否則為0
按位取反~:0->1,1->0
比如: 2&3=?、-2=?、2=?、2|3=?、2^3=?
實例1
public static void main(String[] args) {
//推導過程
/**
* 1、先得到2的補碼
* 2的原碼:00000000 00000000 00000000 00000010
* 正數的原碼、反碼、補碼相同(三合一)
* 2的補碼:00000000 00000000 00000000 00000010
*/
/**
* 2、在得到3的補碼
* 3的原碼:00000000 00000000 00000000 00000011
* 正數的原碼、反碼、補碼相同(三合一)
* 3的補碼:00000000 00000000 00000000 00000011
*/
/**
* 3、按位與計算2的補碼和3的補碼,兩位全為1,結果為1,否則為0.。(注:計算用補碼、結果用原碼)
* 2的補碼:00000000 00000000 00000000 00000010
* 3的補碼:00000000 00000000 00000000 00000011
* 結果:00000000 00000000 00000000 00000010 (這是運算過后得到的補碼)
* 我們在運算后的結果需要看原碼,因為符號位是0為正數,1為負數,所以三碼合一
* 結果的原碼為:00000000 00000000 00000000 00000010
* 將結果二進制數轉為十進制數為:0*(2的1-1次方)+1*(2的2-1次方)=0+2=2
* 所以2&3的結果為:2
*/
System.out.println(2&3);
}
實例2
/**
* 1、先得到-2的原碼:10000000 00000000 00000000 00000010
* 2、在得到-2的反碼:11111111 11111111 11111111 11111101
* 3、得到-2的補碼: 11111111 11111111 11111111 11111110
* 4、取反: 00000000 00000000 00000000 00000001
* 5、將補碼轉為原碼:00000000 00000000 00000000 00000001
* 6、將二進制數轉為十進制數,結果為:1
*/
System.out.println(~-2);
實例3
/**
* 1、先得到2的原碼:00000000 00000000 00000000 00000010
* 2、后得到2的補碼:00000000 00000000 00000000 00000010 (正數三碼合一)
* 3、直接按位取反: 11111111 11111111 11111111 11111101
* 4、補碼轉為反碼: 11111111 11111111 11111111 11111100 (負數的反碼=負數的補碼-1)
* 5、反碼轉原碼: 10000000 00000000 00000000 00000011 (負數的反碼=它的原碼符號位不變,其它位取反(0->1,1->0))
* 6、將二進制原碼轉為十進制結果為:-3
*/
System.out.println(~2);
其他位運算符
還有3個位運算符>>、<<和>>>,運算規則:
1.算術右移>>:低位溢出,符號位不變,并用符號位補溢出的高位
2.算術左移<<:符號位不變,低位補0
3.>>>邏輯右移也叫無符號右移,運算規則是:低位溢出,高位補0
4,特別說明:沒有<<<符號.
應用案例
/**
* 1=> 00000000 00000000 00000000 00000001
* 低位溢出,符號位不變,并用符號位補溢出的高位
* 1向右移動兩位是:00000000 00000000 00000000 00000000 本質是1/2/2=0
*/
System.out.println(1>>2);
/**
* 1=> 00000000 00000000 00000000 00000001
* 1>>2:符號位不變,低位補0:00000000 00000000 00000100 本質:1*2*2=4
*/
System.out.println(1<<2);
/**
* 相當于:4*2*2*2=32
*/
System.out.println(4<<3);
/**
* 相當于:15/2/2 = 3
*/
System.out.println(15>>2);
/**
* 相當于:56/2/2/2/2=3
*/
System.out.println(56>>4);
/**
* 相當于:56*2*2*2*2=896
*/
System.out.println(56<<4);
小插曲
10/3=3
10/5=2
10%2=0
-10.5%3=-1.5(a%b,當a是小數時,公式=a-(int)a/b*b),得到的是近似值
int i = 66;
System.out.println(++i+i);// 結果為66+1+67=134