打開博客園,一篇關於有符號二進制加法溢出的文章吸引了我的好奇。由於沒有基礎,對原博主所說內容並未完全理解,開始在網上搜索尋找各種詳細的解釋,但發現效果都不好。今天花了大半天的時間來研究有符號二進制數加法溢出以及溢出后該如何計算的問題。本文適合沒有任何基礎的初學者。
我想從五個方面來說說有符號二進制加法溢出以及溢出后該如何計算這些個問題:
·什么是有符號二進制數
·補碼的計算以及還原
·有符號數的加法
·什么是溢出、什么是自然丟棄
·溢出后該如何正確計算結果
一.什么是有符號二進制數
二進制數分為有符號和無符號兩種形式,在未標明的情況下,二進制數指的是無符號二進制數,即沒有負數形式。反之,有符號二進制數,是指有正負號的二進制數。
有符號二進制數即在無符號二進制數的基礎上,在最左邊添加符號位,‘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方向思考。如果采用上述算法,那么就需要一個加法器和一個或門相結合的形式,這和只用加法器就能完成的補碼相加計算相比,是不是就多了一步符號位或的操作,這無形中增加了功耗,以及增加了電路的復雜程度。是不是降低或者增加了速度,不好說,那得看或操作延時和位數進位延時哪個時長較長了。我沒有模擬過,在這里沒法給予答案。
這只是我個人對這個思考的個人解讀,如果你有不同的想法,歡迎留言,或者糾正我的錯誤,謝謝!