VC++中的一個不足及其改善方法 (轉)
VC++中的一個不足及其改善方法
上海七○四研究所
梁柏林
---- 使用C語言序,有時需要把一種數值(如float型別的數值)轉換成另一種型別(如int型別)的數值使用,這時,我們就要用到型別強制轉換運算子,如(int)、(float)等。但是在VC++中,當把一個float型別的數值轉換成int型別時,有時會出現比較大的誤差。我在工作過程中就碰到過,當我把一個值為1140.00的float型變數ftemp使用如下方法轉換成int型別,
itemp=(int)ftemp;
這時,int型變數itemp的值為1139,誤差1(在本文中,我稱這種誤差為“1誤差”)。這麼大的誤差,我們是不能接受的。
---- 經過深入的測試研究,我發現:在VC++中,當一個float型變數初始化(從螢幕輸入一值,或把一常量值賦給它)後就用以上方法轉換成int型別,結果是小數部分去掉,整數部分保留,誤差小於1,沒有“1誤差”;而當一個float型變數初始化後,又經過一些運算,再轉換成int型別,就可能會有“1誤差”,就是說,結果不但把小數部分去掉,整數部分也可能有改變。例如,我們把以米為單位的資料轉化成以釐米為單位的資料,用float型變數f存放以米為單位的資料,用int型變數i存放以釐米為單位的資料,使用下面語句實現資料轉換。
i=(int)(f*100); 當f=11.40(米)時,i=1139(釐米);當f=11.41(米)時,i=1140(釐米);當f=12.32(米)時,i=1231(釐米);當f=12.33(米)時,i=1232(釐米);等等,很多資料的轉換存在著“1誤差”。不過,大部分資料的轉換是沒有誤差的,如當f=11.39(米)時,i=1139(釐米);當f=12.31(米)時,i=1231(釐米)。如果改用以下方法實現資料轉換, “1誤差”一樣存在。 float ftemp; ftemp=f*100; i=(int)ftemp; 這裡,ftemp是一區域性變數(內定義)或全域性變數(函式外定義)。把f*100改成f*100.0, “1誤差”也存在。但是如果把ftemp 改成為類的屬性變數(在類裡定義), “1誤差”就不存在。
---- 我還發現,“1誤差”現象對正負數具有對稱性。就是說,如果有“1誤差”,對於正數,(int)轉換後少了1;對於負數,(int)轉換後多了1。如上例子中,當f=-11.40(米)時,i=-1139(釐米);當f=-11.41(米)時,i=-1140(釐米);當f=-12.32(米)時,i=-1231(釐米);當f=-12.33(米)時,i=-1232(釐米)。而且,轉換誤差不會大於1。
---- 針對以上分析結果,我在這裡給出一個校正“1誤差”的方法,以供參考。我設計了一個把float型數轉換成int型數的函式,用以代替(int)運算子。函式清單如下:
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); }
---- 在此函式中,透過判斷(int)型別轉換前後的誤差ferror是否大於0.99來判斷是否有“1誤差”,如果有,就進行校正。校正方法是,對於正數,把(int)轉換結果加1;對於負數,把(int)轉換結果減1。
---- 定義了float_to_int()函式後,用它代替(int)運算子就能校正“1誤差”了。如對上面把以米為單位的資料轉化成以釐米為單位的資料這一例子來說,改成
i=float_to_int(f*100); 或 float ftemp; ftemp=f*100; i=float_to_int(ftemp); 當f=11.40(米)時,i=1140(釐米);當f=11.41(米)時,i=1141(釐米);當f=12.32(米)時,i=1232(釐米);當f=12.33(米)時,i=1233(釐米);當f=-11.40(米)時,i=-1140(釐米);當f=-11.41(米)時,i=-1141(釐米);當f=-12.32(米)時,i=-1232(釐米);當f=-12.33(米)時,i=-1233(釐米)。 “1誤差”沒有了。而且對原來沒有 “1誤差”的資料也沒有影響,如當f=11.39 (米)時,i=1139(釐米)。透過對大量的資料進行測試檢查,證明此方法是有效的。
---- 另外,對於double型轉換成int型,也有類似的“1誤差”問題,只是出現誤差的資料比較少,而且還有偶然性(就是,對於某個數值,有時候有“1誤差”,有時候又沒有“1誤差”)。應用類似的方法也可以把double型轉換成int型的“1誤差”校正過來。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-1005714/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- VC++中STL的使用 (轉)C++
- VC++中程式與多程式管理的方法(轉)C++
- 我的六個系統安裝方法及其應用(轉)
- intervention/image 中的一個小坑及其破解之法
- 我的六個作業系統安裝方法及其應用(轉)作業系統
- Node 中如何引入一個模組及其細節
- VC++中實現程式互斥執行 (轉)C++
- 再談在VB中呼叫VC++開發的DLL (轉)C++
- JS中將一個值轉換為字串的3種方法JS字串
- 改善網站使用者體驗的20個方法網站
- 改善 Python 程式的 91 個建議(一)Python
- VC++ 2017的一個單例模板類C++單例
- VC++介面一攬子解決方案 (轉)C++
- visualbox中linux磁碟不足的解決方法Linux
- Windows系統資源不足的七種處理方法(轉)Windows
- VC++ 的串列埠通訊 (轉)C++串列埠
- JavaScript中的bind方法及其常見應用JavaScript
- Java中的JavaCore/HeapDump檔案及其分析方法Java
- 一個值得學習的精益改善方針
- 物件導向的方法在遊戲中的應用的一個例子(上)(轉)物件遊戲
- 物件導向的方法在遊戲中的應用的一個例子(下)(轉)物件遊戲
- 在VC++中建立自定義資料庫類 (轉)C++資料庫
- VC++獲取不同Windows版本的方法C++Windows
- 一個例項中,多個synchronized方法的呼叫synchronized
- 讓VC++支援中文 (轉)C++
- html中引入另一個html的方法HTML
- 將一個Activity中的資料傳到另一個Activity的Fragment中的方法Fragment
- VC++訊息對映的思考 (轉)C++
- PHP中把stdClass Object轉array的幾個方法PHPObject
- 常見的80004005錯誤及其解決方法 (轉)
- 中國駭客常用的八種工具 及其防禦方法(轉)
- 關於VC++中,兩種自定義訊息的傳送與接收的方法實現進行說明。 (轉)C++
- 9 種改善 AngularJS 效能的方法AngularJS
- 改善C#程式的50種方法C#
- VC++ 控制檯程式中 四種定時器建立方法C++定時器
- 記錄一個Excel中特殊的VLOOKUP方法Excel
- VC++ 執行緒同步(轉)C++執行緒
- VC++/MFC 教程1(英文) (轉)C++