天天看點

Java位運算及補碼存儲一、原碼形式存儲二、反碼形式存儲 三、補碼形式存儲四、總結:1、左移( << ) 2、右移( >> ) 3、無符号右移( >>> )4、位與( & )5、位或( | )6、位異或( ^ ) 7、位非( ~ )           

大家都知道,計算機中二進制數值是以補碼的形式存儲的,那麼為什麼二進制數值在原碼、反碼、補碼中選擇以補碼的形式存儲呢?

一、原碼形式存儲

首先,原碼是站在使用者角度的,是原始的二進制!

求原碼步驟:
  1. 使用者的數字分為正負數,需要有一位存儲符号
  2. 最高位為符号位:0為正,1為負
  3. 左邊是高位,右邊是低位

由原碼的計算方式可以發現源碼存儲會引發2個問題:

(1)0有兩個存儲方式

我們以char型(占1位元組,8位)為例(下同):

+0:    0000 0000

- 0:    1000 0000

不難發現+0和-0的原碼是不一樣的,而在計算過程中,+0和-0是沒有任何差別的。

(2)正數和負數相加,結果不正确(計算機隻會加)

1 - 1 =1 + (-1)

 1:  0000 0001

-1:  1000 0001

          1000 0010  =  -2

很顯然1-1=0,而用原碼進行計算得出的結果卻相差甚遠!

二、反碼形式存儲

既然原碼不适合作為計算機的存儲方式,人們在解決這個問題的過程中又提出了反碼的概念

求反碼步驟:
  1. 求原碼
  2. 符号為不變,其他位取反
  3. 注意:正數原碼、反碼一樣 !

接下來我們檢驗一下1 - 1:

  1:    0000 0001

- 1:    1111 1110

             1111 1111 -> 1000 000 ( 轉換為原碼,因為原碼是站在使用者角度的 )  =  -0

不難可能出反碼已經解決的正負數相加結果不正确的問題

然後我們再檢驗+0、-0

+0  0000 0000

-0   1111 1111

由此看出,反碼并沒有解決0有兩種形式的問題

三、補碼形式存儲

在反碼的基礎上,人們有提出了補碼的概念

求補碼:

補碼為其反碼+1

注意:正數的原碼、反碼、補碼都一樣!

接下來我們對補碼存儲進行驗證:

    +0: 0000 0000

     -0: 原碼:  1000 0000

              反碼:  1111 1111

              補碼:10000 0000(char占1位元組八位,最高位丢棄)= 0000 0000

 可以看出補碼解決了+0 -0不一樣的問題

    +1: 0000 0001

     -1: 1111 1111 

          1 0000 0000(最高位丢棄)= 0000 0000 = 0

 那麼補碼也解決了正負數相加結果不正确的問題! 

四、總結:

補碼是在原碼的基礎上為了适應計算機運算一步一步完善而來,原碼和反碼存儲都有一定的弊端,是以計算機采用補碼存儲!

Java提供的位運算符有:

左移( << )、右移( >> ) 、無符号右移( >>> ) 、位與( & ) 、位或( | )、位非( ~ )、位異或( ^ ),除了位非( ~ )是一進制操作符外,其它的都是二進制操作符。

1、左移( << )

将5左移2位:5<<2

首先會将5轉為2進制表示形式 ( java中,整數預設就是int類型,也就是32位):

0000 0000 0000 0000 0000 0000 0000 0101           然後左移2位後,低位補0:

0000 0000 0000 0000 0000 0000 0001 0100           換算成10進制為20

2、右移( >> ) 

5>>2

還是先将5轉為2進制表示形式:

0000 0000 0000 0000 0000 0000 0000 0101 然後右移2位,高位補0

0000 0000 0000 0000 0000 0000 0000 0001

3、無符号右移( >>> )

我們知道Java中int類型占32位,既可以一個正數,也可以表示負數。其中最高位是符号位,正數為0,負數為1

例如  -5換算成二進制後為(補碼形式:原碼取反 + 1):

1111 1111 1111 1111 1111 1111 1111 1011   

我們分别對5進行右移3位、 -5進行右移3位和無符号右移3位:

5>>3      結果是0

-5>>3     結果是-1

-5>>>3   結果是536870911

5換算成二進制: 0000 0000 0000 0000 0000 0000 0000 0101

5右移3位後結果為0,0的二進制為: 0000 0000 0000 0000 0000 0000 0000 0000     (高位補0)

 -5換算成二進制: 1111 1111 1111 1111 1111 1111 1111 1011

-5右移3位後結果為-1,-1的二進制為: 1111 1111 1111 1111 1111 1111 1111 1111   (高位補1)

-5無符号右移3位後的結果 536870911 換算成二進制: 0001 1111 1111 1111 1111 1111 1111 1111   (高位補0)

通過其結果轉換成二進制後,我們可以發現,正數右移,高位用0補,負數右移,高位用1補,當負數使用無符号右移時,用0進行補位(自然而然的,就由負數變成了正數了)

注意:這裡說的是右移,高位補位的情況。正數或者負數左移,低位都是用0補。

4、位與( & )

5 & 3

5轉換為二進制:0000 0000 0000 0000 0000 0000 0000 0101

3轉換為二進制:0000 0000 0000 0000 0000 0000 0000 0011

-------------------------------------------------------------------------------------

1轉換為二進制:0000 0000 0000 0000 0000 0000 0000 0001

位與:第一個操作數的的第n位于第二個操作數的第n位如果都是1,那麼結果的第n為也為1,否則為0

5、位或( | )

5 | 3

5轉換為二進制:0000 0000 0000 0000 0000 0000 0000 0101

3轉換為二進制:0000 0000 0000 0000 0000 0000 0000 0011

-------------------------------------------------------------------------------------

7轉換為二進制:0000 0000 0000 0000 0000 0000 0000 0111

位或操作:第一個操作數的的第n位于第二個操作數的第n位 隻要有一個是1,那麼結果的第n為也為1,否則為0

6、位異或( ^ )

5 ^ 3

5轉換為二進制:0000 0000 0000 0000 0000 0000 0000 0101

3轉換為二進制:0000 0000 0000 0000 0000 0000 0000 0011

-------------------------------------------------------------------------------------

6轉換為二進制:0000 0000 0000 0000 0000 0000 0000 0110

位異或:第一個操作數的的第n位于第二個操作數的第n位 相反,那麼結果的第n為也為1,否則為0

7、位非( ~ )           

~5

 5轉換為二進制:0000 0000 0000 0000 0000 0000 0000 0101

-------------------------------------------------------------------------------------

-6轉換為二進制:1111 1111 1111 1111 1111 1111 1111 1010

位非:操作數的第n位為1,那麼結果的第n位為0,反之。

由位運算操作符衍生而來的有:

&= 按位與指派

|=  按位或指派

^= 按位非指派

>>= 右移指派

>>>= 無符号右移指派

<<= 指派左移

和 += 一個概念而已。

參考:

https://blog.csdn.net/qq_41727218/article/details/79521759

https://blog.csdn.net/xiaochunyong/article/details/7748713