1。補碼的介紹(two's complement)
在電腦系統中,數值一律用補碼來表示(儲存)。 這樣做的最大好處就是可以將符號位和其它位統一處理;即減法也可按加法來處理。
2.補碼的計算
電腦在儲存有符號數的時候,會分配一個符號位(最高位)給他,因此負數的表示方式為:符號位+數值位。假設為8位機,如
-8 1 0001000
符號位 數值位
補碼的計算方式:1.正數的補碼不變
2.負數的符號位不變,數值位取反後加1
如-8的補碼
1 111 0111 ——>1 111 1000
3. 為什麼採用補碼
書上說這樣用可以簡化硬體的設計,加法與減法的計算方式一樣,其實這樣說是沒錯,可是這樣說卻不太好理解。為了說明問題,我打一個類比,6個人圍成一堆並且給每人一個編號0,1,2,3,4,5.現在讓他們依次報號,從0號開始,當1號第二次報號時,他會報1而不是7,那現在有個問題:1號後面第九個是幾號?如果你挨個數的話會發現剛好是4號,如果讓你用一個算式表示出來,你會怎麼算?(1+9)%6 = 4,這是不是老生常談的模數的問題了,當累計到最大數(5)的時候,會從該範圍內最小的數(0)重新開始。
依然是上一個例子,現在我換一個問題:當前位置是1號,那我怎麼才能得到4號?有兩種方法:1.向前報數,第3個人就是4號 2.向後報數,第3人就是4號。
設向前報數為加法,向後報數為減法,那為了得到4號,我列出下面的資料關係。
當前位置 向前+ 向後- 目標位置 最大值 總數
0 4 2 4 5 6
1 3 3 4 5 6
2 2 4 4 5 6
3 1 5 4 5 6
4 0 6 4 5 6
5 -1 7 4 5 6
向前報號的個數與向後報號的個數之和始終為 6,即總人數。所以可以將數(0,6),(1,5),(2,4),...,(6,0)稱為互補數組。
由以上補數原理得出,當我們需要進行減法運算的時候,可以用加上它的補數來代替,即
2+2 = 4, 2-4 = 2 + (4的補數)= 2+2 = 4
明白了吧,電腦就是利用這樣的原理來實現加減法運算的,它直接將減法運算簡化成了加法運算。
結論:假設數列1,2,3,4,...,n。如果存在n+1 = 1, 1-1 = n這樣的關係,則(1,n),(2,n-1),...(n,1)分別是互補數對,其中任一對互補數之和為n+1。
推論1:由於最小值1與最大值n為互補數,因此最小值與最大值之和等於任一互補數之和。
現在再來看電腦中的資料二進位表示,一個位元組內,最大值二進位 1111 1111 = 2**8-1=255,按我們上面分析看,數字總數為256,那互補的數就是
(1,255),(2,254),...(250,6),...(255,1). 再看其中一組互補數的二進位(1,255)
255 +1 = ? 1111 1111 + 0000 0001 = 1 0000 0000 ——>出現了第9位,電腦自動去掉最高位1——>0000 0000 = 0.
所以對下面代碼的結果為0.如果按照上面的結論,255+1 = 255-255 = 0,結果仍然為0
unsigned char a=255;
a + 1 = 0
那麼電腦怎麼進行減法運算的呢?255-1 = ?再看它的二進位運算
255 - 1 = 255 + -1 = 1111 1111 + 1000 0001 = 1 1000 0000 = 1000 0000 = -0 = 0
這樣看起來不太對啊,我們期望的結果應該是254才對。其實在進行運算的時候資料都是以補碼的形式出現的,上式沒有將負數轉化成補碼,所以得到的結果就會出人意料了,那為什麼在進行加法(即加上正數)的時候可以直接進行運算?那是因為正數的補碼是其本身。現在再看看負數的補碼運算
255 - 1 = 255 + -1 = 1111 1111 + 1000 0001的補碼 = 1111 1111 + 1 111 1110 + 1 = 1 1111 1110 = 1111 1110 = 254
4 負數的補碼運算公式的來曆
說來曆這個詞有點誇大,應該說是自己的推理更恰當一些。
比如說電腦中的char類型,它的取值範圍-128~127,並且127(最大值)+1 = -128(最小值),所以互補數之和應該為127+ -128=-1,127+|-128| = 255.
上式可知,對於位元組char類型,127與-128是互補數,再看其二進位表示
127 0111 1111
-128 1000 0000
-1 1111 1111
沒時間了,推不下去了,有時間的達人可以接著推下去,實在不好意思。