打開博客園,一篇關於有符號二進制加法溢出的文章吸引了個人好奇。因爲沒有基礎,對原博主所說內容並未徹底理解,開始在網上搜索尋找各類詳細的解釋,但發現效果都很差。今天花了大半天的時間來研究有符號二進制數加法溢出以及溢出後該如何計算的問題。本文適合沒有任何基礎的初學者。算法
我想從五個方面來講說有符號二進制加法溢出以及溢出後該如何計算這些個問題:學習
·什麼是有符號二進制數spa
·補碼的計算以及還原博客
·有符號數的加法class
·什麼是溢出、什麼是天然丟棄基礎
·溢出後該如何正確計算結果搜索
一.什麼是有符號二進制數二進制
二進制數分爲有符號和無符號兩種形式,在未標明的狀況下,二進制數指的是無符號二進制數,即沒有負數形式。反之,有符號二進制數,是指有正負號的二進制數。方法
有符號二進制數即在無符號二進制數的基礎上,在最左邊添加符號位,‘0’爲正,‘1’爲負。計算機
舉例說明:-2 1(符號位 ‘1’代表是負數)10(2的二進制表達) --> 110
+2 --> 010
二.補碼的計算以及還原
在計算機的運算中,是以補碼的形式進行加減法運算的(減法其實就是帶負數的加法,2-3 其實就是2+(-3))。那補碼是怎麼計算的呢?
分爲兩種狀況:
1.正數補碼。 記住正數的補碼就是其自己。如:+2 -->010 補碼--> 010
2.負數補碼。 符號位不變,將符號位後面的全部數取反,以後進行加一操做。如:-2 --> 110 補碼 --> 101 + 1 -->110. 能夠發現它的補碼和原碼相同,這裏你們留個心眼,爲後面的溢出埋下伏筆。
學會了原碼轉補碼,怎麼能不會補碼轉原碼呢。
補碼轉原碼其實就是再將補碼進行一次求補碼的操做,即補碼的補碼是原碼。
三.有符號數的加法
ps:本身在學習的過程當中突然有一個思考,拿出來分享一下。
思考:爲何不採用符號進行或操做,數值正常的相加減呢?
接下來就是開始進行加法操做了。在補碼的加法運算中,符號位就當成是整個二進制數的一部分,進行加法運算。
如:+3 + 4
3 --> 0011
4 --> 0100
相加 --------
結果 0111
而後對所得結果求補碼(這點很重要,前面例子發現有些負數的補碼就是其自己,爲了後面不弄混淆,建議對所得結果求補碼)。此處,正數的補碼是其自己。計算結果就是0111。
0 表示正數 111的十進制是7,解爲+7。徹底正確。
提一點若是兩個相加數的位寬不一樣,將小的位寬的數左起填充0,而後再進行補碼操做。
如-2+8 110 + 01000 此處將-2作以下處理。10010(五位保持和+8同樣位寬) 再將10010作補碼處理,-->11101+1-->11110。補碼形式加法爲:11110+01000
接下來請看什麼是溢出,以及溢出的危害是什麼。
四.什麼是溢出、什麼是天然丟棄
對於溢出的理解,稍微解釋的不詳細極可能會把初學者帶入溝裏,今天我就被帶進溝裏了。做爲一個過來人我很願意和你們分享,讓初次接觸的朋友們能很快的理解,避免和我同樣花大量時間從溝裏爬出來。言歸正傳。
說到溢出,仍是要先提一下天然丟棄。
前面的例子是很簡單的例子,請看下面這個例子:
-2 - 6
-2 --> 1110
-6 --> 1010
相加 --------
結果 11000
結果的位數比原先的多出了一位,此處最左邊的1,是會被天然丟棄的(就是不要了)。再看結果,對1000求補碼(其實能夠看出它就是0)。這和咱們想要的-8有天壤之別。爲何會出現這個狀況呢?
緣由就是這裏出現了溢出!
首先來看溢出的定義:
對一個N位二進制補碼,其能夠表達的範圍是 - 2N-1+1 ~ 2N+1 - 1之間。若是超出這個範圍就稱爲溢出了。
拿上面的-2-6來講,咱們剛剛在計算時,轉換爲二進制補碼是4位的。它的取值範圍是-7~+7之間。而咱們想要的結果是-8,比範圍的最小值還要小,這個叫作負溢出。同理若是想要的結果比最大值還要大,那麼就叫作正溢出,如取值範圍是-7~+7之間,想要的結果是+8,那麼就是正溢出。
說完了溢出的定義,咱們來講說溢出的斷定,就是怎麼在計算開始時知道本身算的結果是否是溢出了?
仍是拿前面-2-6爲例,即1110 + 1010,你們能夠看到我拿兩種不一樣顏色標註了它們最開頭的兩個數,咱們把紅色的(左起第一位)符號位進位值和藍色(左起第二位)相加的進位值進行比較。若是二者相同(即00或者11),則不溢出,若是二者不一樣(即01正溢出,10負溢出),則發生溢出,最後的解一定會出錯。
拿-2-6爲例,它們補碼形式爲1110+1010,符號位相加發生了進位,進位值爲1,數字位左起第一位相加沒有發生進位,進位值爲0,即10型溢出,爲負溢出,就是說所得的值小於四位二進制補碼的取值範圍,和咱們計算的-8<-7結果相匹配,判斷成功。
到這裏咱們已經成功了一大半,與最終正確解的就值就差一步之遙。
五.溢出後該如何正確計算結果
在經過判斷以後,咱們知道這個結果定是溢出了,該怎麼求正確的解呢?
答:將位寬擴大一位,仍是按前面的斷定方法進行斷定。
舉例,-2-6 前面說了這是一個負溢出,咱們在轉換爲二進制時進行位寬擴大,以提高取值範圍。
此處 -2 二進制寫成 10010(5位比開始多一位),-6二進制寫成10110(5位比開始多一位)。再進行補碼運算,10010--> 11101+1-->11110,10110-->11001+1-->11010.
11110
11010
相加---------
111000 最高位超出位寬,天然捨棄,剩下的11000求補碼,10111+1-->11000 即-8,和咱們所求的結果一致,bingo答對了。
若是想真的弄懂,必定要本身多給本身作一些練習:
題目:(1)-5-6 (2)+4+8 (3)-4-8
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
不知道你們有思考過個人問題嗎?那種算法其實更符合咱們在計算過程當中的想法。可是爲何不使用這個算法呢?
本人是IC方向的,不妨從IC方向思考。若是採用上述算法,那麼就須要一個加法器和一個或門相結合的形式,這和只用加法器就能完成的補碼相加計算相比,是否是就多了一步符號位或的操做,這無形中增長了功耗,以及增長了電路的複雜程度。是否是下降或者增長了速度,很差說,那得看或操做延時和位數進位延時哪一個時長較長了。我沒有模擬過,在這裏無法給予答案。
這只是我我的對這個思考的我的解讀,若是你有不一樣的想法,歡迎留言,或者糾正個人錯誤,謝謝!