By: Ailson Jack
Date: 2018.11.29
個人博客:http://www.only2fire.com/
本文在我博客的地址是:http://www.only2fire.com/archives/92.html,排版更好,便於學習,也可以去我博客逛逛,興許有你想要的內容呢。
在計算機內部數值是以補碼的方式進行存儲的,採用補碼進行數據存儲當然有其優點,下面會一一介紹相關內容,讓各位徹底弄懂原碼、反碼、補碼的概念以及爲什麼採用補碼作爲數據存儲的方式。
注意:下面列舉的例子均是指8位的字節數據。對於16位,32位的數據同樣適用,只是爲了書寫方便,8位是最好的選擇啦!
1、無符號數與有符號數
在介紹原碼、反碼和補碼的概念之前,先來了解下無符號數和有符號數。
在計算機系統中,我們可以將數分爲兩類:無符號數和有符號數。無符號數的意思是我們不關心這些數的符號,因此也就無所謂正負,反正它們就是數而已,就像小學生一樣,眼中只有自然數。在8位的字節運算中,無符號數的範圍是0000_0000B~1111_1111B,即十進制的0~255。
有符號數是分正負的,而且規定,數的正負要通過它的最高位來辨別。如果最高位是0,它就是正數;如果是1,就是負數。這樣一來,在8位的字節運算環境中,正數的範圍是0000_0000B~0111_1111B,即十進制的0~127;負數的範圍是1000_0000B~1111_1111B,即10進制的-128~-1。也就是說8位的數據,有符號數的範圍是-128~127(對這裏的負數有疑問的可以往下面看)。
2、原碼、反碼與補碼
原碼:最高位表示符號位,其餘位代表數值大小。如果最高位是0,它就是正數;如果最高位是1,就是負數。例如:十進制數+2,其二進制形式爲:0000_0010B;如果是-2,就是1000_0010B。因爲最高位是符號位,所以原碼二進制的形式值不等於真正的數值。例如上面的有符號數1000_0010B,其最高位1代表負數,表示的數值爲-2,而不是形式值130(1000_0010B轉換成無符號十進制等於130)。
反碼:正數的反碼是其本身;負數的反碼是在原碼的基礎上,符號位不變,其餘各數值位取反。
補碼:正數的補碼是其本身;負數的補碼是在其原碼的基礎上,符號位不變,其餘各數值位取反,最後+1(即負數的補碼是其反碼+1)。
下面列舉幾個8位二進制數的原碼、反碼和補碼的編碼形式:
十進制數 |
原碼 |
反碼 |
補碼 |
42 |
0010 1010 |
0010 1010 |
0010 1010 |
-42 |
1010 1010 |
1101 0101 |
1101 0110 |
127 |
0111 1111 |
0111 1111 |
0111 1111 |
-127 |
1111 1111 |
1000 0000 |
1000 0001 |
3、補碼存儲數據的優點
在講述原碼、反碼和補碼時,有一個特殊的數值沒有涉及到,那就是0,在我們平時使用中,0是沒有正負之分的,但是不可否認+0 = -0,那麼下面列舉下+0,-0的原碼、反碼與補碼的形式:
十進制數 |
原碼 |
反碼 |
補碼 |
+0 |
0000 0000 |
0000 0000 |
0000 0000 |
-0 |
1000 0000 |
1111 1111 |
0000 0000 |
爲什麼-0的反碼1111_1111B進行加1操作求取到的-0補碼是0000_0000B。因爲這裏假定數據寬度是8位的,1111_1111B加1之後,會逐個向上進位,我們假定有第9位,且值爲0,那麼0_1111_1111B加1之後,就變成了1_0000_0000B,但是實際上我們要的數據是8位的寬度,這裏捨棄第9位,最後結果就變成了0000_0000B。
好了,在講述補碼的優點之前,先看看計算機爲什麼不使用原碼作爲數的存儲格式而採用補碼作爲數的存儲格式。
下面說說原碼的優缺點吧。
原碼的優點當然是簡單直觀,例如+2的原碼爲:0000_0010B,-2的原碼爲:1000_0010B。
原碼的缺點也顯而易見:
(1)、+0與-0在原碼中竟然有兩個二進制形式,與我們熟知的+0=-0貌似有出入。
(2)、原碼不能直接參加運算,可能會出錯。例如:1+(-1)=0,而用原碼的二進制形式進行運算爲:0000_0001B + 1000_0001B = 1000_0010B,換算成十進制爲-2,顯然計算結果錯誤。
那麼計算機爲什麼要使用補碼呢?
首先,根據運算法則減去一個正數等於加上一個負數,即: 1-1 = 1+(-1),所以計算機被設計成只有加法而沒有減法,而讓計算機辨別”符號位”會讓計算機的基礎電路設計變得十分複雜,於是就讓符號位也參與運算,從而產生了反碼。
用反碼計算,出現了”0”這個特殊的數值,0帶符號是沒有任何意義的。而且會有0000_0000B和1000_0000B兩個原碼編碼表示0。於是設計了補碼,負數的補碼就是反碼+1,正數的補碼就是正數本身,從而解決了0的符號以及兩個編碼的問題:用0000_0000B表示0,用1000_0000B表示-128。
注意:-128並沒有原碼和反碼。使用補碼,不僅僅修復了0的符號以及存在兩個編碼的問題,而且還能夠多表示一個最低數值。
如果還不清楚-128怎麼來的,那麼我就來按我的想法來推出來吧,-127的原碼爲:1111_1111B,則其反碼爲:1000_0000B,補碼爲:1000_0001B,那麼自然我們可以想想補碼爲1000_0000B代表的就是-128=-127-1=1000_0001B - 1= 1000_0000B。這也就是8位數據最小的負整數了。
這就是爲什麼8位二進制,使用補碼錶示的範圍爲[-128,127]。
補碼存儲數據的優點:
(1)、避免了0的編碼有兩個;
(2)、符號位和有效值位可以一起處理,減法通過加法就可以實現,即簡化了計算機的結構設計也提高了運算速度。
補碼存儲數據的缺點:
(1)、不夠簡單直觀。當然這裏的不夠簡單直觀是對我們來說的。計算機倒沒什麼。
下面給大家推薦一個計算補碼的小工具,那就是我們經常使用的Windows計算器,只要選擇好相應的數據寬度,輸入你的數值,就可以觀察到對應的二進制形式了:
好了,講了這麼多,相信大家對原碼、反碼和補碼都有一定的認識了,如果還有什麼疑問,歡迎留言交流。
排版更好的內容見我博客的地址:http://www.only2fire.com/archives/92.html
注:轉載請註明出處,謝謝!^_^