李文昭,王虹,李慶
(1.河北大學(xué) 靜電研究所, 河北 保定 071002;2.河北大學(xué) 電子信息工程學(xué)院, 河北 保定 071002)
隨著電子技術(shù)的不斷發(fā)展,在控制領(lǐng)域廣泛使用的8051系列單片機(jī)也有了長(zhǎng)足的發(fā)展,一些采用新技術(shù)的8051系列單片機(jī)不斷出現(xiàn),如NXP的LPC900系列[1]、STC的1T系列[2]、SiLabs的C8051F[3]系列等,這些產(chǎn)品的計(jì)算能力較傳統(tǒng)8051系列單片機(jī)有了幾十倍甚至上百倍的提升.曾經(jīng)以控制為主的單片機(jī),已有能力進(jìn)行一些相對(duì)復(fù)雜的計(jì)算.然而目前針對(duì)8051的各種C語(yǔ)言編譯器在數(shù)據(jù)類型上僅支持到float型變量[4].Keil作為目前國(guó)內(nèi)使用最廣泛的單片機(jī)集成開發(fā)環(huán)境,雖然支持了“double”關(guān)鍵字,但是其對(duì)double類型的變量仍然只是轉(zhuǎn)為float型處理[4],實(shí)際計(jì)算精度并沒有達(dá)到IEEE-754雙精度浮點(diǎn)數(shù)的標(biāo)準(zhǔn).針對(duì)目前C51編譯器的不足,采用數(shù)組分部處理數(shù)據(jù)[5],在Keil C51環(huán)境下設(shè)計(jì)了符合IEEE-754雙精度標(biāo)準(zhǔn)的浮點(diǎn)庫(kù),實(shí)現(xiàn)基本的四則運(yùn)算,滿足了在控制領(lǐng)域中需要進(jìn)行高精度計(jì)算的特殊要求.
IEEE-754二進(jìn)制浮點(diǎn)數(shù)算術(shù)標(biāo)準(zhǔn)定義了浮點(diǎn)數(shù)的表示格式,是目前廣泛使用的浮點(diǎn)數(shù)格式標(biāo)準(zhǔn),被多數(shù)CPU和浮點(diǎn)運(yùn)算器采用.在IEEE-754標(biāo)準(zhǔn)中規(guī)定了單精度(32位)、擴(kuò)展單精度(43位以上,不常用)、雙精度(64位)和擴(kuò)展雙精度(79位以上)[6-8]4種浮點(diǎn)數(shù)的表示方式.IEEE-754二進(jìn)制浮點(diǎn)數(shù)算術(shù)標(biāo)準(zhǔn)利用科學(xué)計(jì)數(shù)法來(lái)表示實(shí)數(shù),一個(gè)符合IEEE-754的浮點(diǎn)數(shù)F被劃分為3個(gè)字段,表示為如下形式:
F=(-1)S×M×2E,
(1)
其中,F是所表示的浮點(diǎn)數(shù).S是符號(hào)位,占用1位二進(jìn)制數(shù)寬度,E是階碼,也就是指數(shù),用移碼表示,在雙精度浮點(diǎn)數(shù)中階碼占用11位二進(jìn)制數(shù)寬度.M是尾數(shù),通常都是規(guī)格化表示,即非“0”的有效位最高位總是“1”,然而在IEEE-754標(biāo)準(zhǔn)中是一個(gè)純小數(shù),有效位形式為“1.MMM…MMM”,在實(shí)際表示中整數(shù)位的“1”被省略,稱為隱藏位,對(duì)于雙精度浮點(diǎn)數(shù)而言M的寬度是52位二進(jìn)制數(shù),加上1位隱藏位共53位[6-8].由于
253= 9,007,199,254,740,992,
故雙精度浮點(diǎn)數(shù)可以得到15~16位有效數(shù)字,常用的浮點(diǎn)數(shù)格式如表1所示.
表1 常用的浮點(diǎn)數(shù)表示格式
加減法運(yùn)算是最基本的運(yùn)算,因?yàn)锳1-A2=A1+(-A2),故把加法運(yùn)算和減法運(yùn)算放在一起討論.計(jì)算過程主要分為6步:1)0操作數(shù)檢查;2)對(duì)階;3)尾數(shù)相加;4)結(jié)果規(guī)格化;5)舍入處理;6)溢出處理.其中省略了2個(gè)和算法不相關(guān)的步驟,即進(jìn)行第1步之后第2步之前需要分別把符號(hào)位、階碼、尾數(shù)從64位二進(jìn)制串中提取出來(lái);當(dāng)進(jìn)行完第6步后還要把這3部分組合成一個(gè)符合IEEE-754標(biāo)準(zhǔn)的64位二進(jìn)制串.
1)0操作數(shù)檢查.對(duì)2個(gè)操作數(shù)進(jìn)行0檢測(cè),只要有1個(gè)操作數(shù)為0即可簡(jiǎn)化加法運(yùn)算,此時(shí)只要返回另1個(gè)操作數(shù),節(jié)省了運(yùn)算時(shí)間.
2)比較階碼大小并完成對(duì)階.如果2個(gè)操作數(shù)都不為0,則要進(jìn)行階碼比較.當(dāng)其中1個(gè)操作數(shù)的階碼遠(yuǎn)遠(yuǎn)大于另1個(gè)操作數(shù)的階碼時(shí),也會(huì)在很大程度上簡(jiǎn)化運(yùn)算.因?yàn)槲矓?shù)的精度有限,當(dāng)階碼之差大于尾數(shù)寬度時(shí),說(shuō)明其中1個(gè)操作數(shù)遠(yuǎn)大于另外1個(gè),即使相加,結(jié)果也不會(huì)保留到那么高的精度,所以在這種情況下,會(huì)得到和0操作數(shù)檢查幾乎相同的運(yùn)算時(shí)間消耗,只要返回較大的操作數(shù)就可以了.在64位計(jì)算中階碼之差要大于54才能簡(jiǎn)化運(yùn)算.當(dāng)階碼之差小于54時(shí),就需要進(jìn)行對(duì)階和實(shí)際的加法計(jì)算.對(duì)階操作時(shí),要遵循小階向大階看齊的原則,否則會(huì)影響計(jì)算精度.具體的做法是先求出階差,然后階小的尾數(shù)進(jìn)行右移位操作,每右移1位,階碼加1,直到2個(gè)操作數(shù)的階碼相等為止,此時(shí)右移的次數(shù)剛好等于移位前的階差.
3)尾數(shù)相加.對(duì)階完成后即可將2個(gè)尾數(shù)按定點(diǎn)加法運(yùn)算規(guī)則進(jìn)行運(yùn)算.
4)結(jié)果規(guī)格化.當(dāng)計(jì)算完畢,結(jié)果可能已經(jīng)不是“1.XX…X”的形式,這時(shí)就需要進(jìn)行規(guī)格化處理,即通過對(duì)尾數(shù)進(jìn)行左移或右移操作并相應(yīng)的修改階碼,使結(jié)果為規(guī)格化表示.
5)舍入.由于尾數(shù)的位數(shù)被限制為52位,所以在進(jìn)行右移操作時(shí)可能造成低位數(shù)的丟失,這就需要進(jìn)行舍入處理.本程序采用了較為精確的0舍1入法,當(dāng)丟失的部分最高位為0時(shí)不作處理,當(dāng)丟失的部位最高位為1時(shí),則向最低位加1.
6)溢出處理.溢出分為4種情況:階碼上溢,一般認(rèn)為是±∞;階碼下溢,一般將其認(rèn)為是0;尾數(shù)上溢和尾數(shù)下溢,需要對(duì)尾數(shù)重新進(jìn)行規(guī)格化處理[7].
浮點(diǎn)數(shù)的乘法相對(duì)于加法要復(fù)雜一些,2個(gè)浮點(diǎn)數(shù)相乘,乘積的階碼為2個(gè)乘數(shù)階碼之和,乘積的尾數(shù)為2個(gè)乘數(shù)尾數(shù)之積.例如,設(shè)2個(gè)浮點(diǎn)數(shù)A,B:A=2EA×MA,B=2EB×MB, 則A和B的乘積為
A×B=2(EA+EB)×(MA×MB).
(2)
因此,浮點(diǎn)數(shù)的乘法操作可以由4步完成:1)0操作數(shù)檢查;2)階碼求和;3)尾數(shù)求積;4)尾數(shù)規(guī)格化并進(jìn)行舍入處理.
1)0操作數(shù)檢查.和加法操作一樣,只要有一個(gè)操作數(shù)為0則可以直接返回0結(jié)果.
2)階碼求和.把2個(gè)乘數(shù)的階碼相加,結(jié)果為乘積的階碼,相加完畢后要進(jìn)行溢出判斷.溢出判斷的方法是在原有移碼的基礎(chǔ)上再加上一位符號(hào)位,如果計(jì)算后此位為1則說(shuō)明有溢出,溢出后,原符號(hào)位為0說(shuō)明結(jié)果上溢;原符號(hào)位為1說(shuō)明結(jié)果下溢.如果沒有溢出,那么原符號(hào)位為0說(shuō)明結(jié)果為負(fù);原符號(hào)位為1說(shuō)明結(jié)果為正.
3)尾數(shù)求積.尾數(shù)求積可采用定點(diǎn)乘法運(yùn)算的原理.由于尾數(shù)加上隱藏位一共是53位,所以需要一個(gè)至少106位的空間存儲(chǔ)乘積.而C51最大只支持2個(gè)16位數(shù)相乘,因此,需要把尾數(shù)分別存儲(chǔ)在2個(gè)數(shù)組中,把尾數(shù)分為幾段,進(jìn)行計(jì)算的時(shí)候把每段和另一個(gè)尾數(shù)相乘,采用嵌套循環(huán)進(jìn)行乘法處理然后再進(jìn)行相加得到計(jì)算結(jié)果.求積計(jì)算是整個(gè)乘法運(yùn)算中最耗時(shí)的操作.
4)尾數(shù)規(guī)格化并進(jìn)行舍入處理.尾數(shù)求積后得到的結(jié)果受到長(zhǎng)度限制,只能取前53位,然后進(jìn)行舍入處理.舍入處理通常有2種方法:一種是截?cái)嗵幚?把剩余的低位數(shù)據(jù)全部作丟棄處理;另一種辦法是0舍1入.同加法一樣,為了提高計(jì)算精度,這里采用了0舍1入的處理方式.
除法是四則運(yùn)算里面最復(fù)雜的,也是最耗時(shí)的[9-10].除法是乘法的逆運(yùn)算,正如乘法可以用移位相加實(shí)現(xiàn)一樣,除法可以通過一系列的移位相減實(shí)現(xiàn).浮點(diǎn)除法的運(yùn)算規(guī)則是
A/B=2(EA-EB)×(MA/MB).
(3)
商的階碼是兩數(shù)階碼之差,商的尾數(shù)是兩數(shù)尾數(shù)之商.因此,浮點(diǎn)數(shù)的除法操作和乘法一樣可以由4步完成:1)0操作數(shù)檢查;2)階碼求差;3)尾數(shù)求商;4)尾數(shù)規(guī)格化及舍入處理.
尾數(shù)求商是浮點(diǎn)除法運(yùn)算的關(guān)鍵,原碼除法通常采用“恢復(fù)余數(shù)法”和“加減交替法”.設(shè)計(jì)參考了恢復(fù)余數(shù)法并針對(duì)8051單片機(jī)計(jì)算速度慢的特點(diǎn)對(duì)循環(huán)減算法進(jìn)行了改進(jìn)優(yōu)化,恢復(fù)余數(shù)法的特點(diǎn)是當(dāng)除數(shù)為負(fù)時(shí),需加上除數(shù),將其恢復(fù)成原來(lái)的余數(shù);循環(huán)減的特點(diǎn)是先判斷是否夠減,然后再進(jìn)行相應(yīng)的操作.而商的符號(hào)位由除數(shù)和被除數(shù)的符號(hào)進(jìn)行異或運(yùn)算得到,即
SIGN商=SIGN被除數(shù)⊕SIGN除數(shù).
尾數(shù)的除法同樣在Keil C51環(huán)境下遇到無(wú)法用一個(gè)變量表示的問題,解決的方法是用2個(gè)數(shù)組分別存儲(chǔ)2個(gè)尾數(shù),所以在用數(shù)組進(jìn)行除法運(yùn)算的時(shí)候要不斷注意借位問題,以免造成計(jì)算錯(cuò)誤.通過除數(shù)尾數(shù)對(duì)被除數(shù)尾數(shù)進(jìn)行54次循環(huán)減之后,就得到了商.最后把計(jì)算好的階碼和符號(hào)位同商的尾數(shù)組合成標(biāo)準(zhǔn)的64位浮點(diǎn)數(shù)放在指定的存儲(chǔ)空間,浮點(diǎn)除法計(jì)算就完成了.
程序的運(yùn)行效率是用戶比較關(guān)心的問題,如果運(yùn)行時(shí)間太長(zhǎng),那么64位浮點(diǎn)計(jì)算也就失去了意義.可以通過一組數(shù)據(jù)對(duì)加、乘、除分別測(cè)試,表2是經(jīng)過多次測(cè)試得到的一組平均數(shù)據(jù),可以看到3種運(yùn)算的時(shí)間消耗都可以令人滿意.
表2 3種運(yùn)算的耗時(shí)對(duì)比
CPU:AT89C51,OSC CLOCK:12 MHz
由上表可以看出即使是12 MHz的普通8051單片機(jī)進(jìn)行除法計(jì)算耗時(shí)也僅需40 ms左右,如果使用基于CIP-51核等一些新型的單片機(jī)那么3種計(jì)算的時(shí)間將會(huì)少于10 ms,由此看出8051系列的單片機(jī)完全能夠勝任實(shí)時(shí)性要求不高的64位浮點(diǎn)計(jì)算.
當(dāng)庫(kù)函數(shù)完成以后,可利用Keil C51軟件提供的庫(kù)管理程序生成庫(kù)文件,并為浮點(diǎn)庫(kù)編寫相應(yīng)的頭文件,以方便在以后的工程中調(diào)用.
針對(duì)目前最廣泛使用的Keil C51平臺(tái)下無(wú)法進(jìn)行雙精度計(jì)算的實(shí)際問題,提出了一種可行的解決方案.在進(jìn)行理論分析后,設(shè)計(jì)并實(shí)現(xiàn)了四則運(yùn)算的64位雙精度計(jì)算方法.
方案采用分部存儲(chǔ)的方法,將較大的64位數(shù)據(jù)分成幾個(gè)部分存儲(chǔ)在內(nèi)存空間,將各部分分別計(jì)算后再整合成需要的計(jì)算結(jié)果,其中大量使用指針,在充分分析時(shí)間和空間矛盾的基礎(chǔ)上,針對(duì)8051核單片機(jī)有限的內(nèi)存容量和較低的運(yùn)算速度對(duì)程序進(jìn)行了優(yōu)化設(shè)計(jì),和傳統(tǒng)計(jì)算方法相比提高了程序運(yùn)行效率,節(jié)省了存儲(chǔ)空間.
在采用最普通的8051核單片機(jī)AT89C51的情況下,測(cè)試中加減法進(jìn)行一次運(yùn)算僅需要1.6 ms,乘法和除法單次運(yùn)算也只需27.4 ms和36.2 ms,可以滿足絕大多數(shù)實(shí)時(shí)性要求不高的工程需要,解決了目前Keil C51平臺(tái)下無(wú)法進(jìn)行高精度計(jì)算的難題,為8051系列單片機(jī)提供了更廣泛的應(yīng)用空間,同時(shí)避免了使用ARM等32位高端處理器帶來(lái)的人力和財(cái)力支出.
參 考 文 獻(xiàn):
[1] 張立群,李鐵才,連全斌.基于單片機(jī)P89LPC932A1的微功耗設(shè)計(jì)[J].自動(dòng)化技術(shù)與應(yīng)用,2006,25(11):30-33.
ZHANG Liqun, LI Tiecai, LIAN Quanbin. A low power design based on MCU P89LPC932A1[J]. Techniques of Automation & Applications,2006,25(11):30-33.
[2] 宏晶科技.宏晶科技STC12C5410AD系列單片機(jī)器件手冊(cè)[EB/oL].〔2011-9-9〕(2013-1-23).http://www.stcncu.com/datasheet/stc/STC-AD-PDF/STC12C5410AD.PDF
[3] 鐘磊,盧文壯,左敦穩(wěn),等.C8051F單片機(jī)的IAP系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)[J].微處理機(jī),2009,03:9-11.
ZHONG Lei, LU Wenzhuang, ZUO Dunwen, et al. In-application programming system design and realization ofC8051F MCUs[J].Microprocessors,2009,03:9-11.(2013-1-23)〔2012-8-9〕www.keil.com
[4] KEIL Cx51 User’s Guide[EB/OL].Keil An ARM Company.2012.
[5] 狄光智,趙同林.數(shù)組實(shí)現(xiàn)高精度計(jì)算的方法研究[J].電腦編程技巧與維護(hù),2009,10:126-127.
DI Guangzhi, ZHAO Tonglin.The study of high-precision computation using arrays[J]. Computer Programming Skills & Maintenance,2009,10:126-127.
[6] IEEE. IEEE Standard for Binary Floating-Point Arithmetic[S]. IEEE Std 754-2008:6-38
[7] 白中英.計(jì)算機(jī)組成原理[M].北京:科學(xué)出版社, 2008:22-71.
[8] BRYANT, O’HALLARON.深入理解計(jì)算機(jī)系統(tǒng).[M].龔奕利,雷迎春,譯.北京:機(jī)械工業(yè)出版社,2011:50-81.
[9] 陳森林,田華.快速浮點(diǎn)除法運(yùn)算及其在單片機(jī)上的實(shí)現(xiàn)[J].陜西師范大學(xué)學(xué)報(bào):自然科學(xué)版,2004,32(2):43-45.
CHEN Senlin, TIAN Hua. Rapid floating point division algorithm and its implementation on MCS-51 series single chip computer[J]. Journal of Shanxi Normal University: Natural Science Edition, 2004,32(2):43-45.
[10] 郭松,徐世亮,萬(wàn)里勇.巧用數(shù)組實(shí)現(xiàn)除法的高精度計(jì)算[J].計(jì)算機(jī)與信息技術(shù), 2007,36:442,422.
GUO Song, XU Shiliang, WAN Liyong.Using array to achieve high precision of division[J].Science & Technology Information,2007,36:442,422.