本文嘗試用更加淺顯和本質的方式去理解補碼。
人類習慣於用十進位制數進行運算,而計算機的每個位卻只有0和1兩種狀態,換句話說,計算機採用的進製是二進位制。
因此,我們面臨的第乙個問題就是計算機如何用二進位制來表示十進位制數字。
對於正數而言,可以直接用該數的二進位制形式來表示,例如,十進位制數2,其在計算機中的表示為(假設計算機的字長為8):
0000 0010
但是這樣做會帶來乙個問題,如何表示負數呢?為此,我們採用犧牲最高位的辦法,將其視作符號位,並用1表示負,0表示正(這樣做是可以接受的,因為雖然正數的表示範圍由之前的 [1, 255] 縮小到了現在的 [1, 127], 但是我們卻因此收穫了 [-127, -1] 的負數表示範圍;另一方面,引入符號位後,[1, 127] 內的正數的表示方式並沒有發生改變,換句話說,引入符號位前後,正數的表示方法是相洽的)。
例如,十進位制數-2,其二進位制表示現在變為:
1000 0010
這裡,我們便可以引入原碼的概念
原碼:原碼是指乙個二進位制數左邊加上符號位後所得到的碼,且當二進位制數大於0時,符號位為0;二進位制數小於0時,符號位為1。[1]原碼很直觀,人類可以直接理解原碼。
但是原碼是不是完美的呢?很顯然,它是有缺陷的。
1)十進位制數0的原碼並不唯一,以下兩個都是0的原碼。
0000 0000
1000 0000
2)當進行有負數參與的運算時,原碼將暴露更大的缺陷,例如:-3+2:
1000 0011 #-3的原碼
+ 0000 0010 #2的原碼
------------
1000 0101 #-5的原碼
我們得到了-5,這顯然是個錯誤結果。
為此,我們需要介紹補碼這個新概念
補碼:正數和0的補碼就是該數字本身。負數的補碼則是將其對應正數按位取反再加1。[2]例如,2的補碼即為:
0000 0010
-2的補碼為:
# 1. 將-2對應的正數2,按位取反得到:1111 1101
# 2. 1111 1101再加1即得到: 1111 1110,為-2的補碼
1111 1110
0的補碼只有乙個,為:
0000 0000
現在我們再來驗證一下補碼在進行加減運算時是否能得到正確結果,同樣是-3+2:
1111 1101 #-3的補碼
+ 0000 0010 #2的補碼
------------
1111 1111 #-1的補碼
可以看到,我們得到了正確答案。
事實上,補碼是計算機真正用來表示二進位制數的方式,驗證如下:
#include
using std::cout;
intmain()
我們知道數軸上的點與實數是一一對應的,先來看看我們最熟悉的十進位制數在數軸上的排列:
因此,對於數軸上的任意乙個數,其加上乙個正數,則表示其在數軸正方向上移動了一段距離;而減去乙個正數(等價於加上乙個負數),則表示其在數軸負方向移動了一段距離。這是確保我們在進行數的加減時得到正確結果的關鍵。
當我們引入了原碼,那麼數在數軸上又是如何排列的呢,可以驗證,它們的排列變成了下面這個樣子:
注意:0在這裡是乙個關鍵的分界線,對於負數而言,它們的「0」 是1000 0000;而對於正數而言,它們的「0」是0000 0000。
仔細觀察,我們會發現,這個數軸有兩個正方向(這裡我們把加上乙個正數,數字移動的方向定為正方向):當乙個負數加上乙個正數,數字往左邊移動,例如:-3+2,結果變成了-5;當乙個正數加上乙個正數,數字往右邊移動,例如3+2,我們得到5. 這就解釋了為什麼原碼在加減運算中會出錯的原因。
回到補碼,如前所述,乙個負數的補碼就是是將其對應正數按位取反再加1。但是這裡對於補碼的敘述並不直觀,甚至會讓人有點摸不著頭腦,為了更好地理解補碼究竟在做什麼,我們不妨將-2的補碼與其對應正數2的補碼相加,看看會得到什麼結果:
0000 0010 # 2的補碼
+ 1111 1110 #-2的補碼
------------
1 0000 0000
這樣,我們就發現了對乙個負數求補碼的本質:
負數a模的值,等於2補a_補
a補 = 模-絕對值(a)
n2^n
2n,n為字長。例如,對-2求補碼:
-2補= 2^8 - 0000 0010#2的補碼
= 10000 0000 - 0000 0010
=(1111 1111 - 0000 0010) + 1
#即等於2先按位取反,再加1
因此,引入補碼後,數字在數軸上的排列變成了下面這個樣子:
這裡,不僅0只有乙個表示,而且數軸也只有唯一乙個正方向,從而保證了運算的正確性。而這個保證,仔細思考一下就會發現,正是利用了負數a的絕對值與其補碼之和等於模,從而將負數部分的數軸方向調轉。
注:考慮到計算機存在「溢位」的現象,因此更為正確的表示應該採用數環,而不是數軸,不過,理解用的話,數軸足夠了。
為什麼要引入補碼?
答: 1. 0的原碼有兩個,處理起來不方便;2. 原碼不能直接相加減;
引入補碼的好處?
答:1. 0的補碼只有乙個;2. 變減法為加法,即減法和加法共用一套底層電路;3. 補碼之間可以直接相加減,最高位可以接受進製。
[1] 原碼
[2] 補碼
簡單理解補碼
原碼反碼補碼 其中最不容易理解的就是補碼,先來看乙個關於時鐘的例子 10點到8點,中間差了幾個小時?演算法一 10 8 2小時 演算法二 10 24 8 mod 24 2小時從演算法二可以看出,減去乙個數,相當於加上了另乙個正數 只是需要取模 那麼理解補碼就很容易了 假設模為8,佔4位的有符號數 2...
補碼綜合理解
一 名詞解釋 補碼 1 在計算機系統中,數值一律有補碼來表示 儲存 使用補碼,可以將符號位和其他位統一處理 同時,減法也可按加法來處理.另外,兩個用補碼表示的資料相加時候,如果最高位 符號位 有進製,則進製被捨棄.2 補碼與原碼的轉換過程幾乎是相同的 數值的補碼表示也分兩種情況 1 正數的補碼 與原...
補碼原理理解
今天上課靈機一動想到了補碼的原理 補碼是由原碼變換而來,原碼就是帶符號的二進位制數。正數的補碼與原碼一樣,負數的補碼是由原碼取反 除了符號位 後加一得到的。舉個例子 正數 1 的原碼為 0000 0001 對應的補碼為 0000 0001 負數 1 的原碼為 1000 0001 對應的補碼為 111...