布斯乘法以及带符号数的运算
乘法理解
對于最熟悉的十進制乘法很最基本的運算原理就是一個乘數乘以另一個乘數的個位、十位、百位···數字然后求和。比如
放到二進制來看其實它也是這樣的,多位數的乘法就是一個乘數乘上另一個乘數的各位求和。那么:
布斯算法及原理
原理
已經知道兩個二進制數的乘法的實質是上面式子中那樣了,假設例舉的兩個數1101和1110是無符號數,那么作乘法按照下面的式子來:
這里也體現了各位相乘最后求和的思想。按照上面直接來乘可以看到是要計算三位非0位與乘數的積然后求和,如果說一個乘數的非零位特別多1111111111110,那么運算次數就會更多。而布斯算法很好地解決了這個問題。既然加法會乘這么多次那么用減法就好了。所以上面的1110可以寫成10000-10那么只用乘兩次再作減就可以得到結果了,所以這就是布斯算法的原理。通過把求和轉換成求差簡化運算的次數。
具體算法
算法的基本思想是在乘數的末位添加一個"0",乘數中出現連續的"0"和連續的"1"處不進行任何運算;出現"10"時,作減法;出現"01"時作加法。每次只做一位乘法,因而每一步都右移一位。(來自于《計算機系統基礎》)
依然以1101和1110為例(依然為無符號數),被乘數是1101,乘數是1110,我們知道:
上面的過程就體現了布斯算法的簡化。由上面觀察1110 -> 01110 -> (10000 - 10),把這個減法式子統一到一個位串里可以寫成100(-1)0。上面的減法是為了簡化運算,選什么數來作減可以把原來為1的位簡化成0呢?明顯是高位比11…10…0還高一位的100…00…0減去高位與11…10…0末位1同位的00…10…0序列,而01就標示出了一段連續1的開頭,而10也標示出了一段連續1的結尾,只是開頭的地方是加,而結尾的地方是減去(不知道說清楚沒有),對于連續的1在轉化過后明顯都變成了0所以這些位就不用理睬。
下面實際地計算一下這兩個無符號數1101和1110,結果和中間結果取8位:
帶符號數的計算
無符號數按照常規的方法可作如下計算(依然沿用前面的例子):
得到的答案是正確的,但是當1101和1110是帶符號數的時候,這個答案就不對。難道用常規方法就不能進行帶符號數的運算嗎。當時在看這部分的時候,書上有一句話“對于帶符號整數乘法,大多數處理器中會使用專門的補碼乘法器來進行運算,一位補碼乘法稱為布斯乘法”,所以那個時候在還不太了解布斯乘法,所以誤以為該算法無法進行帶符號數的運算。其實后來發現,常規算法也是可以計算的,但是結果為什么不對,原因在于:以上兩個數為例,進行乘法時中間數其實是乘數和被乘數被擴展成8位后進行各位相乘再截斷為8位得到的,所以還是先看成無符號數把位填充滿得到的是如下:
而之前算不對原因并非在于是否使用了布斯乘法,而是進行擴展的時候依然按照無符號數的方式進行了0擴展,得到的結果自然不對。
現在把上面的數看成符號數處理,1101 = -3, 1110 = -2,所以正確計算后的結果應該是6:
00000110 = 6計算正確。但是這樣的方式計算真的好長,因為非0位太多而要進行7次累加,換成布斯算法:
更加簡單了,所以實際運算的時候使用的是補碼乘法器運用布斯算法專門對帶符號數進行運算。
布斯算法在乘法器中的應用
現在有兩個帶符號數a = -2和b = -3,他們在乘法器中的運算如下:
a與b補碼的長度和為8位,又因為被乘數的末尾也可能是連續1的結尾,所以添加一個附加位0以能夠作出10標志的識別。所以首先設一個P,長度為4 + 4 + 1 = 9,還有A和S,初始值如下:
每一次都讀取P的末兩位來判斷現在是進行加操作還是減操作,加減操作過后每次還需要把P向右移,此處是算數右移。通過上面的描述其實能對應到之前講的算法。P在10時作減,前面說過作減可以通過加負數補碼解決,也就是加上S等同于作減法。P在01時作加,也就直接用P加A就行。分錯開的初始值使得被乘數b與乘數a,不會被交疊而影響到對被除數中各位數的讀取,而多次運算移位的過程其實就是手寫運算時各位做乘,得到中間值然后累加的過程:
總結
以上是生活随笔為你收集整理的布斯乘法以及带符号数的运算的全部內容,希望文章能夠幫你解決所遇到的問題。