大家都知道,計算機中二進制數值是以補碼的形式存儲的,那麼為什麼二進制數值在原碼、反碼、補碼中選擇以補碼的形式存儲呢?
一、原碼形式存儲
首先,原碼是站在使用者角度的,是原始的二進制!
求原碼步驟:
- 使用者的數字分為正負數,需要有一位存儲符号
- 最高位為符号位:0為正,1為負
- 左邊是高位,右邊是低位
由原碼的計算方式可以發現源碼存儲會引發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 - 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