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