-
沿著線條走,你能否發現各種溢出?!
位元據的表示方法有原碼,反碼,補碼。
原碼即一個資料其本身的表示方式,未經過任何修改的表示方法。如 [0001 1011](27), [1001 1011](-101)
反碼在形式上是原碼按位取反的結果。正數的原碼是其原碼本身,負數的反碼可由其原碼最高符號位不變,其餘按位取反得到。發現,反碼可以表示有符號有符號整數,從 -127 ~ +127 但會出現 [0000 0000] (+0)與 [1111 1111] (−0)。補碼可以填補反碼的不足。有趣的是,通過反碼能只通過加法來實現無符號的加減法運算。對於 4 位位元,x+~x+1=2^4,很明顯 [0011] + [1100] + 1 = [1 0000] ,這個結論很重要。
加法就不用解釋了,即是模 2^4 加法,但減法是如何變換,能通過加法實現。比如,不帶正負號的整數減法 6-11 。
0---------------------><------15
「4-7」就是一個螞蟻在座標 4 往負方向走 7 步,但是會溢出,所以返回座標的尾端 15 繼續往負方向行走,這個過程和這隻螞蟻在座標 4 往正方向走 (16-7) 步是一樣的,而 (16-7)恰好等於 (~7+1)。所以 4-7=4+~7+1=14 。所以,一個加法器可以實現加減法,即把螞蟻的負向行走(減法)轉換成正向行走(加法)。會發現,這就是補碼加法。
補碼。正數和 0 的補碼是其本身,負數的補碼則最高符號位不變,其餘按位取反加 1 ,如 [0001 1011] 補碼為其本身, [1001 1011] 補碼為 [1110 0100] 。有趣的是,補碼錶示中,在w位的二進位表示中,最高的有效位被解釋為負權,權重相應是負的,為 -2^( w-1 ) 。如
- [0101 0001] = -0*2^7 + 1*2^6 + 0*2^5 + 1*2^4 + 0*2^3 + 0*2^2 + 0*2^1 + 1*2^0 = -0 + 64 + 0 + 16 + 0 + 0 + 0 + 1 = 81
- [1101 0001] = -1*2^7 + 1*2^6 + 0*2^5 + 1*2^4 + 0*2^3 + 0*2^2 + 0*2^1 + 1*2^0 = -128 + 64 + 0 + 16 + 0 + 0 + 0 + 1 = 47
上面所說,補碼規避了反碼的不足:有兩個 0 表示。在補碼中 0 只有一種表示即 [0000 0000] , 而 [1000 0000] 也因為負權的原因只能表示最小的負數 -128 , [0111 1111] 即最大的正數 127 ,補碼所能表示的範圍是 -128 ~ 127 。
以 4 位二進位運算 4-7 為例,特地給出有負數的情況,正數來說,有符號和無符號預案明顯是一樣的。而4 位二進位有符號整數 -7 即為 4 位二進位不帶正負號的整數的 9 。有如下
- 無符號運算:4-7=4+(-7)=[0100]+~[0111]+1=[1101]=13(用上面的反碼方法)
- 有符號運算:4-7=4+(-7)=[0100]+[1001]=[1101]=-3(用補碼加法)
發現兩者運算過程一樣,結果實質上是相同的,只是機器對有符號和無符號的解釋不同,因此大多數電腦使用相同的機器指令來執行無符號或者有符號的加法(減法可以代換為加法執行)。
-7 和 9是同餘的,更多關於同餘的概念:同餘式 。
- ∵ 4≡4(mod 16)
- 又 ∵ -7≡9(mod 16)
- 根據同餘式性質,得到:-7+4≡9+4(mod 16)
-
同餘式性質 保持加法、減法和乘法
既然,對於模 16 ,4-7 和 4+9 的結果相同,CPU何不只設計只具備後者(加法)的組件?
同理,對與其他情況:
-1≡15(mod 16)
-2≡14(mod 16)
-3≡13(mod 16)
...
又一個例子:
- 無符號運算:1-5=[0001]+[1011]=[1100]=12 (為了直觀,省略了上面的反碼轉換)又一個例子舉例:
- 有符號運算:1-5=[0001]+[1011]=[1100]=-4 (紅色部分是加法器的實際操作)
回到螞蟻的例子,有符號中的負向走 5 步的 -5 ,可轉變是正向走 11 步的 11,減法即被消除。上電腦群組成原理課程的時候,我們經常背誦,減去一個數,就等於加上這個數的補碼。補碼的出現整合了無符號和有符號加減運算過程,無論機器對位元的解釋如何,加法器所做的工作相同。當然有符號或者無符號運算都會出現正溢負溢的情況,這時需要模 2^w 操作(w:二進位位元)。一直很想寫這篇文章,但礙於不知道能不能講清楚,所以擱置了很久,關於電腦原碼,反碼,補碼的問題,如果你有更好的想法,不吝指教。
搗亂 2013-4-11
daoluan.net