一、背景知識
整數在內存中是以二進制的形式存在的,而且存的是該整數的補碼。最高位代表符號位,正數為0,負數為1
正數的補碼是其二進制本身,負數的補碼則是 符號位保持1不變,其他位按位取反再加1,+0和-0的補碼相同,都是0。
負數在進行按位與運算時是以補碼形式參與運算。(這個很好理解,因為負數在內存中本身就是以補碼存儲的)
二、移位運算
下面介紹三種移位運算,
首先我們對5作運算。
5在內存中的存儲形式為:0000 0000 0000 0000 0000 0000 0000 0101
1、左移<<
符號位會被保留,數值位左移一位,低位補0,變為:
0000 0000 0000 0000 0000 0000 0000 1010
得到值為10
2、右移>>
符號位會被保留,數值位左移一位,數值位高位補0,變為:
0000 0000 0000 0000 0000 0000 0000 0010
得到值為2
可以看到,左移相當於乘以2,右移相當於除以2,JDK中很多源碼都采用了這種寫法,效率高而且優雅
3、無符號右移>>>
>>>在右移時會將符號位當做數值位處理,一起右移,高位補0
為了清楚地演示出符號位的變化,以-5為例:
-5在內存中的存儲形式為:1111 1111 1111 1111 1111 1111 1111 1011
>>>1 后得到: 0111 1111 1111 1111 1111 1111 1111 1101
值為2147483645,很明顯,無論從10進制數值,還是從內存中的存儲,都能看出,該值比Integer的最大值小2
代碼如下:
/** * @Description: * @projectName:JavaTest * @see:PACKAGE_NAME * @author:鄭曉龍 * @createTime:2019/5/15 23:30 * @version:1.0 */ public class ShiftOperationTest { public static void main(String[] args) { System.out.println(5<<1); System.out.println(5>>1); System.out.println(-5>>>1); System.out.println(Integer.MAX_VALUE); } }
運行結果:
10 2 2147483645 2147483647
最后,強迫症來了,為什么沒有<<<
我認為是這樣的:內存中是將整數以二進制的補碼形式存放,最高位是符號位,左移時最高位有可能是1或0,符號位不能確定,也就無法滿足無符號左移的定義,而右移可以規定高位補0,即可以確保符號位為0。