王德超
摘要:機(jī)器數(shù)是計(jì)算機(jī)相關(guān)原理如運(yùn)算器設(shè)計(jì)等的基礎(chǔ),也是計(jì)算機(jī)數(shù)值運(yùn)算的前提與基礎(chǔ)。該文給出了一種更簡(jiǎn)便的機(jī)器數(shù)轉(zhuǎn)換算法,并給出了實(shí)現(xiàn)該算法的C++源代碼。
關(guān)鍵詞:機(jī)器數(shù);算法;機(jī)器字長(zhǎng);溢出;C++源代碼
中圖分類號(hào):TP312文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2012)16-3872-03
Machine Number Fast Conversion Algorithm
WANG De-chao
(College of Fundation Education,Sichuan Normal University, Chengdu 610066, China)
Abstract: Number of machines is the basis for computer-related design principles such as operations, is also a prerequisite and basis for nu merical computing. This article gives a simpler machine conversion algorithm, and C++ source code that implements the algorithms are given.
Key words: machine number; algorithm; machine length; overflow; C++ source code
1真值數(shù)與機(jī)器數(shù)
計(jì)算機(jī)中常采用數(shù)的符號(hào)和數(shù)值一起編碼的方法來(lái)表示數(shù)據(jù),即二進(jìn)制數(shù)真值用機(jī)器數(shù)來(lái)表示,機(jī)器數(shù)通常有原碼、反碼和補(bǔ)碼三種表示方法。在計(jì)算機(jī)的運(yùn)算過程中,根據(jù)不同的運(yùn)算運(yùn)用不同的機(jī)器數(shù),以簡(jiǎn)化計(jì)算機(jī)的運(yùn)算過程[1]。如乘法和除法用原碼參與運(yùn)算比較方便,符號(hào)位通過異或運(yùn)算即得結(jié)果的符號(hào)位;而加法與減法運(yùn)算用補(bǔ)碼參與運(yùn)算比較方便,它使符號(hào)位不用單獨(dú)處理,直接與數(shù)值位(尾數(shù))一起參與運(yùn)算。
計(jì)算機(jī)中表示一個(gè)數(shù)值型數(shù)據(jù)應(yīng)包含三個(gè)因素:
1)采用什么進(jìn)位計(jì)數(shù)制; 2)如何表示數(shù)值符號(hào); 3)如何確定小數(shù)點(diǎn)位置。計(jì)算機(jī)中的數(shù)均存放在寄存器中,通常稱寄存器的位數(shù)為機(jī)器字長(zhǎng)。所謂無(wú)符號(hào)數(shù),即沒有符號(hào)的數(shù),在寄存器中的每一位均用來(lái)存放數(shù)值,當(dāng)存放有符號(hào)數(shù)時(shí),則需要留出字長(zhǎng)的最高位位置用于存放數(shù)值符號(hào)。
機(jī)器數(shù)是指在計(jì)算機(jī)內(nèi)的數(shù)據(jù)表示形式,一般是采用某種編碼形式表示帶符號(hào)的二進(jìn)制數(shù)。在計(jì)算機(jī)內(nèi),數(shù)值的符號(hào)位也用二進(jìn)制數(shù)碼0和1來(lái)表示,0表示正號(hào),1表示負(fù)號(hào),且規(guī)定字長(zhǎng)的最高位作符號(hào)位。真值數(shù)則是指機(jī)器數(shù)所對(duì)應(yīng)的帶有+或-符號(hào)的實(shí)際二進(jìn)制數(shù)值。例如+125與-125兩個(gè)數(shù)的二進(jìn)制真值數(shù)分別是+1111101和-1111101,它們的原碼機(jī)器數(shù)分別是01111101和11111101,即數(shù)值的符號(hào)位被二進(jìn)制數(shù)字化了。
2原碼、反碼與補(bǔ)碼
數(shù)制轉(zhuǎn)換是計(jì)算機(jī)組成原理相關(guān)課程的重要組成部分[1-6]。計(jì)算機(jī)科學(xué)中所采用的數(shù)制包括十進(jìn)制數(shù)、二進(jìn)制數(shù)、十六進(jìn)制數(shù)和八進(jìn)制數(shù)等。但計(jì)算機(jī)中的數(shù)均采用二進(jìn)制數(shù)表示,數(shù)的正負(fù)號(hào)也是用二進(jìn)制表示,這樣的數(shù)稱為機(jī)器數(shù)。原碼、反碼和補(bǔ)碼是機(jī)器數(shù)的三種形式。一個(gè)正的十進(jìn)制數(shù)的原碼、反碼和補(bǔ)碼為將該十進(jìn)制數(shù)轉(zhuǎn)換成位數(shù)為機(jī)器字長(zhǎng)的二進(jìn)數(shù)本身。一個(gè)負(fù)的十進(jìn)制數(shù)的補(bǔ)碼轉(zhuǎn)換過程:先轉(zhuǎn)換出最高位為1的長(zhǎng)度為機(jī)器字長(zhǎng)的該負(fù)數(shù)的原碼,再求其反碼,然后在反碼的最低位加1得出補(bǔ)碼。這便是傳統(tǒng)的三種機(jī)器相互轉(zhuǎn)換的方法。該文將給出不用“反碼加1”求負(fù)數(shù)補(bǔ)碼的快捷方法。
2.1原碼
規(guī)則:機(jī)器數(shù)的最高一位表示符號(hào),“0”表示正號(hào);“1”表示負(fù)號(hào),后面各位用數(shù)的二進(jìn)制絕對(duì)值表示。若字長(zhǎng)為n位,整數(shù)真值x=±xn-1xn-2…x2x1的原碼一般可表示為0xn-1xn-2…x2x1(正數(shù))與1xn-1xn-2…x2x1(負(fù)數(shù))。如真值x=+0101010與y=-0101010的原碼分別是x原=00101010與y原=10101010。
2.2反碼
反碼通常作為原碼與補(bǔ)碼相互轉(zhuǎn)換的中間過渡。反碼的簡(jiǎn)便轉(zhuǎn)換方法是:當(dāng)為正數(shù)時(shí),其反碼和原碼的形式相同;當(dāng)為負(fù)數(shù)時(shí),反碼為保持原碼的符號(hào)位不變,原碼的數(shù)值部分各位按位變反。如真值x=+ 0101010與y=-0101010的反碼分別是x反=00101010與y
反=11010101。
2.3補(bǔ)碼
計(jì)算機(jī)中通過補(bǔ)碼可將減法轉(zhuǎn)換為加法實(shí)現(xiàn),這部分由計(jì)算機(jī)硬件來(lái)完成。CPU中同時(shí)有加法指令和減法指令,采用補(bǔ)碼的目的是可以運(yùn)算或存儲(chǔ)有符號(hào)數(shù)。補(bǔ)碼是計(jì)算機(jī)專業(yè)課中的重要知識(shí)點(diǎn),如《計(jì)算機(jī)組成原理》與《C語(yǔ)言》等[3,6]課程需要補(bǔ)碼知識(shí)。補(bǔ)碼的傳統(tǒng)轉(zhuǎn)換方法:正數(shù)的補(bǔ)碼就是其原碼,負(fù)數(shù)的補(bǔ)碼為其反碼再最低位加二進(jìn)制數(shù)1。如真值x=+0101010與y=-0101010的補(bǔ)碼分別是x補(bǔ)= 00101010與y補(bǔ)=11010110。
2.4負(fù)數(shù)原碼與補(bǔ)碼相互變補(bǔ)的簡(jiǎn)捷算法
規(guī)則:符號(hào)位保持不變,尾數(shù)自低位向高位數(shù)第一個(gè)1及其右邊的各低位0保持不變,其左邊的各高位按位變反。如設(shè)機(jī)器字長(zhǎng)為8位:
1)x原=1.1010000→x補(bǔ)=1.0110000;2)x原=10001010→x補(bǔ)=11110110;3)真值-0.10101:原碼1.1010100補(bǔ)碼1.0101100。
2.5三種機(jī)器數(shù)的關(guān)系
1)正數(shù)的原碼、反碼與補(bǔ)碼形式完全相同,不用轉(zhuǎn)換。
2)最高位都表示符號(hào)位,補(bǔ)碼和反碼的符號(hào)位可作為數(shù)值位的一部分一起參加運(yùn)算,但原碼的符號(hào)位不允許和數(shù)值位同等看待,必須分開處理。
3)原碼和反碼各有兩種零的表示法,而補(bǔ)碼只有惟一種零。
4)原碼、反碼表示的正、負(fù)數(shù)范圍相對(duì)零來(lái)說是對(duì)稱的,但補(bǔ)碼負(fù)數(shù)表示范圍較正數(shù)表示范圍寬1,能多表示一個(gè)最負(fù)的數(shù),即絕對(duì)值最大的負(fù)數(shù)。如字長(zhǎng)為1字節(jié)的計(jì)算機(jī)補(bǔ)碼機(jī)器數(shù)能表示的有符號(hào)十進(jìn)制范圍是-128~+127。
5)負(fù)數(shù)反碼與補(bǔ)碼機(jī)器數(shù)間的關(guān)系:補(bǔ)碼=反碼+1,或:反碼=補(bǔ)碼-1。
3計(jì)算真值數(shù)的三種機(jī)器數(shù)的C++源代碼
根據(jù)上面給出的三種機(jī)器數(shù)的相互轉(zhuǎn)換方法,特別是負(fù)數(shù)的原碼與補(bǔ)碼的快速變補(bǔ)算法,設(shè)計(jì)出如下C++源代碼,可用于實(shí)現(xiàn)三種機(jī)器數(shù)的轉(zhuǎn)換工具。
#include
#include
#include
using namespace std;
char a[17],b[17];//假設(shè)機(jī)器字長(zhǎng)為16位
void ctrans(int x) {/*此函數(shù)的功能為將任
意十進(jìn)制整數(shù)x轉(zhuǎn)換為二進(jìn)制原碼機(jī)器數(shù)*/ int i=0,j=0,y,rem; //用于保存余數(shù)
for(i=0;i<17;i++)b[i]=0;i=0;
if(x<0) {b[0]=1;y=abs(x);}
else y=x;
do {rem=y%2; y=y/2;
a[i]=48+rem;//"0"的ASCII碼為48
i++;}while(y!=0);j=16-i;
while(i>0){b[j]=a[--i];++j;}
/*前面do循環(huán)已使i多增加1故用--i
cout.width(16);cout.setf(ios::left||ios::fixed);*/} void main() {int s,r,i;char c[17],d[17];
//c,d分別用于存放反碼和補(bǔ)碼
cout<<"從鍵盤輸入一個(gè)十進(jìn)制正整數(shù):"; cin>>s;ctrans(s);
cout<<"十進(jìn)制數(shù)"< if(b[0]==0){strcpy(c,b);strcpy(d,b);} else {strcpy(c,b);strcpy(d,b); r=strrchr(b,1)-b; for(i=1;i<16;i++){if(b[i]==0)c[i]=1; else c[i]=0;} for(i=1;i else d[i]=0;}} cout<<"十進(jìn)制數(shù)"< cout<<"十進(jìn)制數(shù)"< 4補(bǔ)碼運(yùn)算 4.1補(bǔ)碼運(yùn)算的規(guī)則 [X+Y]補(bǔ)=[X]補(bǔ)+[Y]補(bǔ); [X-Y]補(bǔ)=[X+(-Y)]補(bǔ)=[X]補(bǔ)+[-Y]補(bǔ)。 可見,在計(jì)算機(jī)中,當(dāng)數(shù)用補(bǔ)碼表示時(shí),加法與減法可統(tǒng)一為“加法”運(yùn)算。符號(hào)位也參加運(yùn)算;相加后,如果符號(hào)位有進(jìn)位出現(xiàn),要把這個(gè)進(jìn)位舍去(自然丟失);運(yùn)算結(jié)果本身就是補(bǔ)碼。當(dāng)轉(zhuǎn)換為真值時(shí),若符號(hào)位為0,數(shù)位不變;若符號(hào)位為1,則應(yīng)按前面介紹方法進(jìn)行機(jī)器數(shù)轉(zhuǎn)換后才能獲得其真值。如:設(shè)X=83D=+1010011, Y=37D=+0100101,計(jì)算X-Y: [X]補(bǔ)=01010011, [-Y]補(bǔ)= 11011011, [X]補(bǔ)+[-Y]補(bǔ)=[X補(bǔ)-Y補(bǔ)]=100101110=00101110 (高位1丟失,溢出)=46D,結(jié)果正確。又如:設(shè)X=54,Y=-121,X-Y=175D, X= +0110110,Y= -1111001,[X]補(bǔ)=0,0110110,[-Y]補(bǔ)=0,1111001,[X]補(bǔ)-[Y]補(bǔ)=[X]補(bǔ)+[-Y]補(bǔ)=1,0101111=-1010001=-81D (數(shù)值位向符號(hào)位進(jìn)位,數(shù)值溢出),結(jié)果錯(cuò)。 4.2補(bǔ)碼溢出的判斷 計(jì)算機(jī)機(jī)器字長(zhǎng)決定了所能表示的數(shù)據(jù)范圍。一旦運(yùn)算結(jié)果超出能表示的數(shù)據(jù)范圍,就會(huì)產(chǎn)生溢出。發(fā)生溢出會(huì)導(dǎo)致運(yùn)算結(jié)果錯(cuò)誤,計(jì)算機(jī)必須判斷是否產(chǎn)生溢出。異號(hào)數(shù)相加時(shí),實(shí)際是兩數(shù)的絕對(duì)值相減,不可能產(chǎn)生溢出,但有可能出現(xiàn)正常進(jìn)位;同號(hào)數(shù)相加時(shí),實(shí)際上是兩數(shù)的絕對(duì)值相加,既可能產(chǎn)生溢出,也可能出現(xiàn)正常進(jìn)位。 無(wú)論采用何種機(jī)器數(shù),只要運(yùn)算的結(jié)果大于計(jì)算機(jī)字長(zhǎng)所能表示數(shù)的范圍,就會(huì)產(chǎn)生溢出。如對(duì)于字長(zhǎng)為n的機(jī)器能表示有符號(hào)整數(shù)范圍為-2n-1~2n-1-1。如上面示例,補(bǔ)碼運(yùn)算存在符號(hào)位進(jìn)位自然丟失而運(yùn)算結(jié)果正確的情況,因此,應(yīng)區(qū)分補(bǔ)碼的溢出與正常進(jìn)位。機(jī)器是正常進(jìn)位還是溢出的判定依據(jù):當(dāng)補(bǔ)碼運(yùn)算結(jié)果中最高位和次高位均無(wú)進(jìn)位產(chǎn)生,或均產(chǎn)生進(jìn)位,則結(jié)果正確;當(dāng)最高位和次高位中只有一位產(chǎn)生了進(jìn)位則結(jié)果是錯(cuò)誤的。在微機(jī)中可用異或門電路來(lái)實(shí)現(xiàn)這種判斷。 5結(jié)束語(yǔ) 該文在闡述機(jī)器數(shù)的傳統(tǒng)計(jì)算方法的基礎(chǔ)上,提出了一種快速準(zhǔn)確的原碼與補(bǔ)碼相互變補(bǔ)的速算方法,實(shí)際應(yīng)用中,用傳統(tǒng)方法計(jì)算機(jī)器數(shù)易出錯(cuò),采用速算方法,效率和準(zhǔn)確度都會(huì)有所提高。該文還根據(jù)機(jī)器數(shù)的速算算法,設(shè)計(jì)了計(jì)算真值數(shù)的三種機(jī)器數(shù)的C++源代碼。 參考文獻(xiàn): [1]王玉龍,付曉玲,方英蘭.計(jì)算機(jī)導(dǎo)論[M]. 3版.北京:電子工業(yè)出版社,2010. [2]中國(guó)高等院校計(jì)算機(jī)基礎(chǔ)教育改革課題研究組.中國(guó)高等院校計(jì)算機(jī)基礎(chǔ)教育課程體系[M].北京:清華大學(xué)出版社,2004. [3]譚浩強(qiáng).C程序設(shè)計(jì)[M]. 4版.北京:清華大學(xué)出版社,2010. [4]鄧超成,趙勇.大學(xué)計(jì)算機(jī)基礎(chǔ)-Office 2003+VFP 6.0版[M].北京:科學(xué)出版社,2009. [5]王愛英.計(jì)算機(jī)組成與結(jié)構(gòu)[M].北京:清華大學(xué)出版社,2001. [6]徐孝凱.C++語(yǔ)言.基礎(chǔ)教程[M]. 2版.北京:清華大學(xué)出版社,2007.cout<cout<cout<