C++數(shù)值類型轉(zhuǎn)換方法

字號:

使用C語言編程序,有時需要把一種數(shù)值(如float類型的數(shù)值)轉(zhuǎn)換成另一種類型(如int類型)的數(shù)值使用,這時,我們就要用到類型強制轉(zhuǎn)換運算符,如(int)、(float)等。但是在VC++中,當(dāng)把一個float類型的數(shù)值轉(zhuǎn)換成int類型時,有時會出現(xiàn)比較大的誤差。我在工作過程中就碰到過,當(dāng)我把一個值為1140.00的float型變量ftemp使用如下方法轉(zhuǎn)換成int類型,itemp=(int)ftemp; 這時,int型變量itemp的值為1139,誤差1(在本文中,我稱這種誤差為“1誤差”)。這么大的誤差,我們是不能接受的。
     經(jīng)過深入的測試研究,我發(fā)現(xiàn):在VC++中,當(dāng)一個float型變量初始化(從屏幕輸入一值,或把一常量值賦給它)后就用以上方法轉(zhuǎn)換成int類型,結(jié)果是小數(shù)部分去掉,整數(shù)部分保留,誤差小于1,沒有“1誤差”;而當(dāng)一個float型變量初始化后,又經(jīng)過一些運算,再轉(zhuǎn)換成int類型,就可能會有“1誤差”,就是說,結(jié)果不但把小數(shù)部分去掉,整數(shù)部分也可能有改變。例如,我們把以米為單位的數(shù)據(jù)轉(zhuǎn)化成以厘米為單位的數(shù)據(jù),用float型變量f存放以米為單位的數(shù)據(jù),用int型變量i存放以厘米為單位的數(shù)據(jù),使用下面語句實現(xiàn)數(shù)據(jù)轉(zhuǎn)換。
     i=(int)(f*100);當(dāng)f=11.40(米)時,i=1139(厘米);當(dāng)f=11.41(米)時,i=1140(厘米);當(dāng)f=12.32(米)時,i=1231(厘米);當(dāng)f=12.33(米)時,i=1232(厘米);等等,很多數(shù)據(jù)的轉(zhuǎn)換存在著“1誤差”。不過,大部分數(shù)據(jù)的轉(zhuǎn)換是沒有誤差的,如當(dāng)f=11.39(米)時,i=1139(厘米);當(dāng)f=12.31(米)時,i=1231(厘米)。如果改用以下方法實現(xiàn)數(shù)據(jù)轉(zhuǎn)換,“1誤差”一樣存在。 float ftemp; ftemp=f*100; i=(int)ftemp;這里,ftemp是一局部變量(函數(shù)內(nèi)定義)或全局變量(函數(shù)外定義)。把f*100改成f*100.0,“1誤差”也存在。但是如果把ftemp改成為類的屬性變量(在類里定義),“1誤差”就不存在。
    我還發(fā)現(xiàn),“1誤差”現(xiàn)象對正負數(shù)具有對稱性。就是說,如果有“1誤差”,對于正數(shù),(int)轉(zhuǎn)換后少了1;對于負數(shù),(int)轉(zhuǎn)換后多了1。如上例子中,當(dāng)f=-11.40(米)時,i=-1139(厘米);當(dāng)f=-11.41(米)時,i=-1140(厘米);當(dāng)f=-12.32(米)時,i=-1231(厘米);當(dāng)f=-12.33(米)時,i=-1232(厘米)。而且,轉(zhuǎn)換誤差不會大于1。
    針對以上分析結(jié)果,我在這里給出一個校正“1誤差”的方法,以供參考。我設(shè)計了一個把float型數(shù)轉(zhuǎn)換成int型數(shù)的函數(shù),用以代替(int)運算符。函數(shù)清單如下:
    int float_to_int(float f){ int i; float ferror; i=(int)f; ferror=f-(float)i; if(fabs(ferror)<0.99) //有“1誤差”,校正 if(f<0) i++; else i--; return(i);}
    在此函數(shù)中,通過判斷(int)類型轉(zhuǎn)換前后的誤差ferror是否大于0.99來判斷是否有“1誤差”,如果有,就進行校正。校正方法是,對于正數(shù),把(int)轉(zhuǎn)換結(jié)果加1;對于負數(shù),把(int)轉(zhuǎn)換結(jié)果減1。
    定義了float_to_int()函數(shù)后,用它代替(int)運算符就能校正“1誤差”了。如對上面把以米為單位的數(shù)據(jù)轉(zhuǎn)化成以厘米為單位的數(shù)據(jù)這一例子來說,改成i=float_to_int(f*100);或 float ftemp; ftemp=f*100; i=float_to_int(ftemp);當(dāng)f=11.40(米)時,i=1140(厘米);當(dāng)f=11.41(米)時,i=1141(厘米);當(dāng)f=12.32(米)時,i=1232(厘米);當(dāng)f=12.33(米)時,i=1233(厘米);當(dāng)f=-11.40(米)時,i=-1140(厘米);當(dāng)f=-11.41(米)時,i=-1141(厘米);當(dāng)f=-12.32(米)時,i=-1232(厘米);當(dāng)f=-12.33(米)時,i=-1233(厘米)。“1誤差”沒有了。而且對原來沒有“1誤差”的數(shù)據(jù)也沒有影響,如當(dāng)f=11.39(米)時,i=1139(厘米)。通過對大量的數(shù)據(jù)進行測試檢查,證明此方法是有效的。
    另外,對于double型轉(zhuǎn)換成int型,也有類似的“1誤差”問題,只是出現(xiàn)誤差的數(shù)據(jù)比較少,而且還有偶然性(就是,對于某個數(shù)值,有時候有“1誤差”,有時候又沒有“1誤差”)。應(yīng)用類似的方法也可以把double型轉(zhuǎn)換成int型的“1誤差”校正過來。