數值型數據的運算

定點加法與減法運算

上節內容介紹過,帶符號數有原碼、反碼、補碼等幾種表示方法,並且爲了降低運算器的複雜性,我們可以把減法看作被減數加減數的負數,即

A-B=A+(-B)

這樣減法操作就可以用加法操作來代替,運算器只需要設置加法器即可,無須再設置減法器。此外,由於原碼加法運算複雜,還需要考慮雙方操作數的符號位。而計算機中的有模運算A+(-B)中的-B可以用它的補碼來代替,實現相對簡單,運算過程中無須再額外考慮符號位。因而現代計算機中都採用補碼做加減運算。

1.補碼加減運算

運算器中補碼加減的基本公式如下:

[A+B]補=[A]補+[B]補

[A-B]補=[A+(-B)]補=[A]補+[-B]補

公式表明,當作加減運算時,可直接將補碼錶示的兩個操作數[A]補和[B]補相加。只要結果不超出機器字長所能表示的數值範圍,符號位可與數值位等同處理。如果符號位在運算過程中產生向上進位,根據前面講述補碼時關於有模運算的概念可知,運算器會自動捨去,不會影響結果的正確性。當然,也可能由於加減運算的結果超出了機器字長所能表示的範圍而產生錯誤(稱爲溢出)的情況。

【例】已知十進制數A=+18,B=+23.設機器字長爲8位,用補碼加減計算[A+B]補並還原成真值。

使用二進制表示:

A=+10010,B=+10111

求A和B的原碼,得

[A]原=00010010,[B]原=00010111

求A和B的補碼,得

[A]補=00010010,[B]補=00010111

根據補碼加減公式,得

[A+B]補=[A]補+[B]補=00010010+00010111,結果爲:

[A+B]補=00101001

[A+B]原=00101001

A+B=(41)10進制

【例】已知十進制數A=-10,B=-2.設機器字長爲5位,用補碼加減法計算[A+B]補並還原成真值。

使用二進制形式表示:

A=-1010,B=-0010

求A和B的原碼,得

[A]原=11010,[B]原=10010

求A和B的補碼,得

[A]補=10110,[B]補=11110

根據補碼加減公式,得

[A+B]補=[A]補+[B]補=10110+11110=110100(機器字長爲5,故最高位溢出丟棄)

故[A+B]補=10100                     補碼的補碼即爲原碼

[A+B]原=11100

A+B=-12

【例】已知二進制純小數A=+0.1001,B=+0.0101.設機器字長爲5位,使用補碼加減法計算[A+B]補並還原成真值。

求A和B的原碼,得

[A]原=0.1001,[B]原=0.0101(實際編碼不存在小數點)

求A和B的補碼,得

[A]補=0.1001,[B]補=0.0101

根據補碼加減公式,得

[A+B]補=[A]補+[B]補=0.1001+0.0101=0.1110

A+B=0.1110

當作減法操作A-B時,經過公式推導可知:只需先求出[-B]補,就可以按照加法規則[A-B]補=[A]補+[-B]補進行運算。

【例】已知二進制純小數A=+0.1001,B=+0.0101.設機器字長爲5位,使用補碼加減法計算[A-B]補並還原成真值。

-B=-0.0101

[A]原=0.1001,[-B]原=1.0101

[A]補=0.1001,[-B]補=1.1011

根據補碼加減公式,得

[A-B]補=[A]補+[-B]補=0.1001+1.1011=10.0111(最高位1溢出丟棄)

即 [A-B]補=0.0100                            A-B=(0.01)2進制

【例】已知十進制數A=-71,B=+43.設機器數字長爲8位。用補碼加減法計算[A-B]補並還原成真值。

使用二進制形式表示:

A=-1000111,-B=-101011

求A和B的原碼,得

[A]原=11000111,[-B]原=10101011

求A和B的補碼,得

[A]補=10111001,[-B]補=11010101

根據補碼加減公式,得

[A-B]補=[A]補+[-B]補=10111001+11010101=110001110(最高位1溢出丟棄)

即[A-B]補=10001110 

[A-B]原=11110010

A-B=-114

2.溢出判斷

前面的例題的正確實際上都還要有一個共同的前提:運算結果沒有超出機器字長所能表示的數值範圍。我們知道,計算機運算器中進行的都是有模運算,機器字長所能表示的數值範圍有限。所以,必須考慮運算結果是否超出機器數所能表示的範圍。

【例】已知十進制數A=+71,B=+63.設機器數字長爲8位。用補碼加減法計算[A+B]補並還原成真值。

使用二進制形式表示:

A=+1000111,B=+111111

求A和B的原碼,得

[A]原=01000111,[B]原=00111111

求A和B的補碼,得

[A]補=01000111,[B]補=00111111

根據補碼加減公式,得

[A+B]補=[A]補+[B]補=01000111+00111111=10000110

爲[A+B]補=10000110

[A+B]原=11111010

A+B=-122

得到還原後的真值發現很明顯的錯誤:兩個正數相加,結果卻爲負數。這是因爲8位有符號定點整數的取值範圍爲-128~+127,而上例中的A+B的數學運算結果應爲134,已經超出了取值範圍。在計算機中,這種由於運算結果超出機器數所能表示的範圍而導致的錯誤現象稱爲溢出。下面我們來分析一下,什麼時候可能會產生溢出,運算器中如何判斷一個運算結果是否溢出。

首先,簡單分析不難發現,兩個不同符號的數相加或兩個相同符號的數相減,由於結果的絕對值一定會小於其中一個或兩個操作數的絕對值,所以結果一定不會出現溢出。只有符號不同的兩個數相減或符號相同的兩個數相加,結果的絕對值一定會大於兩個操作數的絕對值,纔有可能出現溢出。

下面我們以機器字長爲5位的有符號數的加減爲例,通過多個實例的分析,尋找溢出發生的規律,從而找到判斷溢出的方法。

【例】5+4=9(未溢出)

轉換爲補碼進行計算,得

00101+00100=01001

【例】12+7=19(溢出)  下列均爲補碼運算

01100+00111=10011

【例】-10+(-2)=-12(未溢出)

10110+11110=110100——10100(丟棄最高位)

【例】-10+(-8)=-18(溢出)

10110+11000=101110——01110

【例】-5-12=-5+(-12)=-17(溢出)

11011+10100=101111——01111

【例】10-5=10+(-5)=5(未溢出)

01010+11011=100101——00101

【例】-10-(-5)=-10+5=-5(未溢出)

10110+00101=11011

從上面可以看出,機器字長爲5位的有符號定點整數的取值範圍爲-16~15(即-2^n~2^n  -1),數值運算的結果超出這個範圍的即溢出。

(1)溢出判斷方法一。不論是減法運算還是加法運算,在計算機中是通過補碼變換,使用加法器進行兩個補碼的加法運算來實現的。只要同時滿足下面兩個條件,即爲溢出:

第一,加法器中實際參加加法運算的兩個補碼符號位相同;

第二,加法器輸出結果與這兩個操作數的符號不同。

設加法器中實際參加加法運算的兩個補碼符號位分別爲SA和SB,加法器輸出結果爲Sr,那麼判斷溢出的邏輯表達式爲:

V=`SA`SBSr+SASB`Sr

【例】設二進制小數A=-0.1011,B=-0.0111.使用溢出判斷方法一判斷定點小數的運算:A+B的結果是否溢出。

求A和B的原碼,得

[A]原=1.1011,[B]原=1.0111

計算操作數的補碼,得

[A]補=1.0101,[B]補=1.1001

[A+B]補=[A]補+[B]補=1.0101+1.1001=10.1110——0.1110

參與加法運算的兩個補碼:1.0101和1.1001的符號位相同,均爲1,而補碼加法後的結果0.1110的符號位爲0,與操作數的符號不同。據此判斷,A+B的結果溢出。

【例】設二進制純小數A+0.1001,B=+0.0101.使用溢出判斷方法一判斷定點小數的運算:A+B的結果是否溢出。

求A和B的原碼,得

[A]原=0.1001,[B]原=0.0101

求A和B的補碼,得

[A]補=0.1001,[B]補=0.0101

根據補碼加減公式,得

[A+B]補=[A]補+[B]補=0.1001+0.0101=0.1110

參與加法運算的兩個補碼:0.1001和0.0101的符號位相同,均爲0,而補碼加法後的結果0.1110的符號位爲0,與操作數的符號相同。據此判斷,A+B的結果未溢出。

(2)溢出判斷方法二。除了方法一,還可以從兩個進位信號之間的關係中找到規律:分別爲符號位產生的進位Cf和最高有效位(符號位右邊第一位)產生的進位C。當符號位和最高有效數值位均產生進位,或均不產生進位時,補碼加法運算沒有出現溢出;而當符號位和最高有效位中只有一個產生進位,而另一個沒有產生進位時,運算結果溢出。所以我們總結出第二個判斷溢出的邏輯表達式爲:

V=Cf異或C

(3)溢出判斷方法三。第三種方法相對簡單,但需要對補碼的編碼方式稍作改變,這種編碼方式稱爲變形補碼:相對普通的補碼,變形補碼還需要一個額外的一個符號位,兩個符號位的取值相同,分別位於機器數編碼的最高位和次高位,也稱雙符號位。例如,一個機器數字長爲5位的補碼爲:01001,它的變形補碼的編碼爲001001,當然,這是加法器中的寄存器字長也需要擴充一位,即6位。再如,當補碼爲10101101時,對應的變形補碼的編碼爲:110101101.設真值A的變形補碼用[A]補`來表示,使用變形補碼進行定點數的加減運算時,其公式和使用普通補碼進行加減運算的公式相似:

[A+B]補`=[A]補`+[B]補`

[A-B]補`=[A+(-B)]補`=[A]補`+[-B]補`

一般情況下,數據在存儲器中仍保持單符號位,在將補碼送入加法器進行運算之前,再擴充爲兩位符號位,運算結果也是變形補碼形式。然後再將結果去掉一位符號位,變成普通補碼形式存入存儲器。使用變形補碼的雙符號位的作用就是判斷運算結果是否溢出的。

下面我們以6位字長的變形補碼的加減爲例,分析並找出判斷溢出的方法:

【例】5+4=9(未溢出)

000101+000100=001001

【例】12+7=19(溢出)

001100+000111=010011

【例】6-(-9)=6+9=15(未溢出)

000110+001001=001111

【例】5-(-11)=5+11=16(溢出)

000101+001011=010000

【例】-5-10=-5+(-10)=-15(未溢出)

111011+110110=1110001——110001

【例】-5-12=-5+(-12)=-17(溢出)

111011+110100=1101111——101111

【例】10-5=10+(-5)=5(未溢出)

001010+111011=1000101——000101

【例】-10-(-5)=-10+5=-5(未溢出)

110110+000101=111011

觀察運算結果發現,變形補碼加法的結果的兩位符號位如果不相等,表示計算結果出現溢出。當結果的兩位符號位相等,則表現未出現溢出。此時將結果去掉一位符號位,結果被還原成普通補碼形式。所以,設變形補碼加法運算後的結果第一位符號位和第二位符號位分別用Sf1和Sf2表示,則第三個判斷溢出的邏輯表達式爲:

V=Sf1異或Sf2

【例】設二進制純小數A=0.1001,B=0.1101,使用溢出判斷方法三判斷定點小數的運算A+B的結果是否溢出

求A和B的原碼,得

[A]原=0.1001,[B]原=0.1101

求A和B的變形補碼,得

[A]補`=00.1001,[B]補`=00.1101

[A+B]補`=[A]補`+[B]補`=00.1001+00.1101=01.0110

變形補碼運算結果爲:01.0110,兩個符號位不一致,可以判定,運算結果溢出。

定點乘法運算

計算機中,乘法運算是非常常用的一種運算,但是由於計算機中實現乘法運算比實現加減法運算要複雜很多,也有一些簡單的CPU內不設置乘法器,乘法的實現是按照乘法器做乘法運算的流程,以加法器爲基礎,用軟件編程的方式實現的。下面我們就來討論乘法運算在計算機中的實現步驟。

定點乘法運算的實現方法很多,難易程度也不同。我們以原碼1位乘運算爲例,介紹計算機中實現定點乘法的基本思想和方法。

(1)符號位。首先是符號位的確定。與定點數的補碼加減法運算不同,乘法運算的符號位無法通過轉換補碼,加入到乘法運算中,必須單獨進行處理。根據乘法運算規則:同號相乘爲正、異號相乘爲負。設兩個定點數分別爲X和Y,Xf和Yf分別代表定點數X和Y的符號位,乘法運算結果爲Z,Zf代表Z的符號位結果。如下所示(0正1負)

乘法運算符號位結果真值表
Xf Yf Zf
0 0 0
0 1 1
1 0 1
1 1 0

 

根據真值表,可得乘法運算符號位的邏輯表達式爲:

Zf=Xf異或Yf

(2)數值部分乘法。然後,除去符號位,再單獨考慮被乘數和乘數的絕對值的乘法運算。原碼一位乘法的方法是從筆算乘法演變而來的,我們先看一個乘法運算筆算式子的完整過程。

【例】設二進制純小數X=0.1101,Y=0.1011,計算X*Y

                                 0  .  1  1  0  1

                          ×     0  .  1  0  1  1

------------------------------------------------------

       0   .     0    0    0  0    1  1   0   1……………………X*2^-4   X右移4位

      0     .     0  0      0 1    1  0   1    ……………………X*2^-3   X右移3位

       0    .     0  0      0 0    0  0         ……………………X*0

       0    .     0  1      1 0    1             ……………………X*2^-1   X右移1位

------------------------------------------------------

       0.         1  0      0  0   1  1   1    1  

結果爲:X*Y=0.10001111

根據上面的例子可得,二進制數的乘法X*Y的絕對值計算方法爲:查看乘數Y的各位上的值,當爲0時,記中間結果0;當爲1時,記中間結果爲X右移相應位數。然後將中間結果累加起來。

我們可以根據這種方式,以移位器和加法器爲基礎,或者編寫程序代碼,實現乘法運算。但是直接使用筆算乘法的方式,計算機需要更多額外的寄存器來存放這些中間結果。而且每一箇中間結果的位數都比被乘數和乘數增加一倍,實現起來效率不高。所以,我們對上例的筆算乘法稍作一些改進,使其更方便地在計算機中實現(若X或Y爲負數,則要取絕對值):

|X*Y|=X*0.1011

        =0.1X+0.001X+0.0001X

        =0.1X+0X+0.001(X+0.1X)

        =0.1X+0.01(0X+0.1(X+0.1X))

        =0.1(X+0.1(0X+0.1(X+0.1X)))

        =2^-1(X+2^-1(0X+2^-1(X+2^-1X)))

        =2^-1(X+2^-1(0X+2^-1(X+2^-1(X+0))))

被乘數乘以2^-1相當於乘數右移一位。觀察上式,可以發現,計算X*Y的絕對值的操作,被表示成了一個先相加再右移的遞歸操作。這無論對於使用硬件方式進行乘法操作,還是對於軟件編程方式進行乘法操作,都是非常容易實現的。下面我們分部計算上例的乘法:

①計算X+0,得中間結果0.1101;

②中間結果右移一位,得中間結果0.01101;

③上步的中間結果+1X,得中間結果1.00111;

④上步的中間結果右移一位,得中間結果0.100111;

⑤上步的中間結果+0X,得中間結果0.100111;

⑥上步的中間結果右移一位,得中間結果0.0100111;

⑦上步的中間結果+1X,得中間結果1.0001111;

⑧上步的中間結果右移一位,得最終結果0.10001111.

這樣,乘法運算被分解爲了簡單的加法操作和移位操作。總結一下,設Y=0.Y1Y2……Yn,X^*爲被乘數X的數值部分。對公式進行分步求解,可以得出二進制乘法操作的分步操作,步驟如下所示:

Z0=0

Z1=2^-1(Z0+X*Yn)

Z2=2^-1(Z1+X*Yn-1)

………………

Zi=2^1(Z(i-1)+X*Y(n-i+1))

………………

Zn=2^-1(Z(n-1)+X*Y1)

每個步驟中產生的這些中間結果:Z0,Z1,Z2,……Zn-1,我們稱之爲部分積。最後的Zn即爲X*Y的結果Z的絕對值。

再加上上面講到的符號位的處理,可得出原碼一位乘法的完整算法如下:

①將被乘數和乘數的符號位進行異或操作:Zf=Xf異或Yf,得到結果的符號位。然後使用被乘數和乘數的數值部分進行計算,計算結果的絕對值。

②設部分積Z0位0.

③以乘數的最低位作爲乘法的判別位,若判別位爲1,則在部分積上加上被乘數,結果右移一位,若判別位爲0,則在部分積上加0,結果右移一位。如此形成新的部分積。

④乘數右移一位。

⑤重複執行第三步和第四步,共執行n次,n爲乘數數值部分長度。最後得到的部分積結果就是乘法結果的絕對值部分。

⑥將乘法操作的符號位和絕對值部分結合起來,得到乘法操作的最終結果。

【例】設二進制存小數X=-0.1001,Y=0.1010,試使用原碼一位乘法計算X*Y,並寫出詳細的運算步驟。

求X和Y的原碼

[X]原=1.1001,[Y]原=0.1010

首先計算符號位,Xf=1,Yf=0,得

Zf=Xf異或Yf=1異或0=1

被乘數X的數值部分爲X*=0.1001,乘數爲0.1010.按照原碼一位乘法運算步驟如下:

①部分積Z0=0,乘數爲0.1010;

②乘數最低位爲0,Z0+0=0,結果右移一位,得Z1=0;

③乘數右移一位,得0.0101;

④乘數最低位爲1,Z1+X*=0.1001,結果右移一位,得Z2=0.01001;

⑤乘數右移一位,得0.0010;

⑥乘數最低位爲0,Z2+0=0.01001,結果右移一位,得Z3=0.001001;

⑦乘數右移一位,得0.0001;

⑧乘數最低位爲1,Z3+X*=0.101101,結果右移一位,得Z4=0.0101101.即X*Y的絕對值爲:0.0101101.

符號位與絕對值部分結合,得最終結果:

[Z]原=1.0101101

Z=-0.0101101

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章