Java移位运算符:<<,>>,>>>
Java移位運算符:<<,>>,>>>
最近在看jdk的源碼,里面還是有很多地方用到了移位操作的,但是本人因為不怎么使用移位操作,基本是看了過一段時間就忘了,忘了用到的時候再看… …
所以在這里寫下這篇博客,以后如果再忘記了直接翻回來看。
Java中有三種移位運算符,分別是左移運算符(<<),有符號右移(>>),無符號右移(>>>),作用分別如下:
左移運算符(<<):將數值的所有二進制位左移給定的位數,高位即左邊的二進制位溢出則丟棄,低位空出來的部分補0
有符號右移(>>):將數值的所有二進制位右移給定的位數,高位空出來的補符號位,即負數補1,正數補0,;低位溢出的部分直接丟棄
無符號右移(>>>):將數值的所有二進制位右移給定的位數,高位空出來的補0,不論正數還是負數;低位溢出的部分直接丟棄
需要注意的是,移位的所有操作都是對數值的補碼進行操作的!!!
我們知道數值有原碼、反碼、補碼三種表示形式,在計算機里的整數值都是以補碼的形式存儲的。對于正數來說,原碼=反碼=補碼;對于負數來說,反碼等于原碼除符號位之外各位取反,補碼等于反碼末位加一。
也就是說我們只需要關心負數的補碼即可,并且負數原碼反碼補碼中轉換的規則是通用的,即原碼=補碼除符號位之外各位取反末位加一,而補碼=原碼除符號位之外各位取反末位加1。當然你也可以先減1然后除符號位之外各位取反。
補碼:1000 0000 …這樣的數很特殊,它是沒有原碼的。當數值為16位時,10000000 00000000的真值為-32768,32位時10000000 00000000 00000000 00000000的真值為-2147483648。
我們通過下面的代碼來驗證:
public class ShiftOptionsDemo {/*** 1(int):* 源碼:00000000 00000000 00000000 00000001* 反碼:與源碼相同* 補碼:與源碼相同** -1(int):* 源碼:10000000 00000000 00000000 00000001* 反碼:11111111 11111111 11111111 11111110* 補碼:11111111 11111111 11111111 11111111** << :左移* >> : 有符號右移* >>> : 無符號右移** 左移會將補碼的所有比特位向左移動* 有符號右移將所有比特位移動后“空出來”的比特位會補符號位,負數補1,正數補0* 無符號右移移動后“空出來”的比特位會補0,不管是正數還是負數** 編譯器(可能不是全部的編譯器)發現移動的位數等于或超過數值本身的位數后,會* 對這個移動的位數進行取模操作, 也就是說一個int型的變量x,x << 32 等價于 x << 1*/public static void main(String[] args) {/** 結果:4* 1補碼* 00000000 00000000 00000000 00000001 = 1* 左移2位后的補碼* 00000000 00000000 00000000 00000100 = 4*/System.out.println(1 << 2);/** 結果:-4* -1補碼* 11111111 11111111 11111111 11111111 = -1* 左移2位后的補碼:* 11111111 11111111 11111111 11111100* 轉換成原碼:* 10000000 00000000 00000000 00000100 = -4*/System.out.println(-1 << 2);/** 結果:0* 1補碼* 00000000 00000000 00000000 00000001 = 1* 有符號右移2位后的補碼:* 00000000 00000000 00000000 00000000 = 0*/System.out.println(1 >> 2);/** 結果:-1* -1補碼* 11111111 11111111 11111111 11111111 = -1* 有符號右移2位后的補碼:* 11111111111111111111111111111111111 = -1*/System.out.println(-1 >> 2);/** 結果:0* 1補碼* 00000000 00000000 00000000 00000001 = 1* 無符號右移2位后的補碼:* 00000000 00000000 00000000 00000000 = 0*/System.out.println(1 >>> 2);/** 結果:1073741823* -1補碼* 11111111 11111111 11111111 11111111 = -1* 無符號右移2位后的補碼:* 00111111 11111111 11111111 11111111 = 1073741823* 這個時候負數就變成了正數*/System.out.println(-1 >>> 2);//輸出:1073741823System.out.println(0b00111111111111111111111111111111);/** 11111111 11111111 11111111 11111111 = -1* 無符號右移一位后的結果:* 01111111 11111111 11111111 11111111 = 2147483647*/System.out.println(-1 >>> 1);//輸出:2147483647System.out.println(0b01111111111111111111111111111111);} }大多數情況下,左移1位相當于乘2,有符號右移相當于除2,但是也有很多特殊的數不符合。比如:
010000000 00000000 00000000 0000000本身是個正數,左移1位后就成負數了,并且就是1000 …這樣的負數了。
-1有符號右移怎么移都是-1,因為-1的補碼是:11111111 … 11111111,根據有符號右移的規則,-1的二進制補碼再怎么移都還是它本身。
總結
以上是生活随笔為你收集整理的Java移位运算符:<<,>>,>>>的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RubyOnRails培训大纲
- 下一篇: java前端面试题