2010-08-05 142 views
10

http://www.learncpp.com/cpp-tutorial/25-floating-point-numbers/ 我已經瞭解這個最近審查C++。避免舍入誤差(具體地浮動)C++

在一般的計算課堂教授往往不會涵蓋這些小事情,雖然我們知道舍入誤差意味着什麼。

有人可以幫助我如何避免舍入誤差?

該教程顯示了一個示例代碼

#include <iomanip> 
int main() 
{ 
    using namespace std; 
    cout << setprecision(17); 
    double dValue = 0.1; 
    cout << dValue << endl; 
} 

此輸出

0.10000000000000001

默認浮子保持精度的6位數字。因此,當我們重寫默認值,並要求更多(在這種情況下,17 !!),我們可能會遇到截斷(正如教程中所解釋的那樣)。 對於雙,最高的是16

在一般情況下,如何做好C++程序員避免舍入誤差? 你們一直在看數字的二進制表示嗎?

謝謝。

+3

設置精度流格式化代碼使用 - 與數字的表示方式無關,或在其他代碼中使用。 – 2010-08-05 23:45:40

回答

0

大多數浮點輸出程序看看如果答案是非常接近的時候在基地10輪的答案實際上是即使在輸出表示是偶數。通過這種方式設置精度,可以使這個過程短路。

這個舍入是完成的,因爲甚至在基數10中出現的答案几乎都不會在基數2(即在內部表示數字的基數)中是偶數(即結束於無限長的尾部0的串)。但是,當然,輸出程序的總體目標是呈現數量的方式有用的一個人,和世界上大多數人在今天閱讀基地數量10

0

短版 - 你可以」當你試圖以基數2表示基數爲10的數字(即,使用浮點數或雙精度數來表示小數)時,真的避免舍入和其他表示錯誤。你幾乎不得不計算你實際有多少有效數字,或者你必須切換到一個(較慢)的任意精度庫。

0

換句話說,儘量減少舍入誤差,它可以幫助保持數十進制定點(實際上與整數工作)。

#include <iostream> 
#include <iomanip> 

int main() { 

    using namespace std; 

    cout << setprecision(17); 

    double v1=1, v1D=10; 
    cout << v1/v1D << endl; // 0.10000000000000001 


    double v2=3, v2D=1000; //0.0030000000000000001 
    cout << v2/v2D << endl; 

    // v1/v1D + v2/v2D = (v1*v2D+v2*v1D)/(v1D*v2D) 

    cout << (v1*v2D+v2*v1D)/(v1D*v2D) << endl; // 0.10299999999999999 

} 
0

你想用所謂的「固定」,所以他們做一個科學記數法不圓或顯示以正確格式的數字操縱你使用固定後,您還可以使用設置精度()函數設置值的位置在右側。 小數點。該示例將如下使用您的原始代碼。

#include <iostream> 
#include <iomanip> 
    int main() { 
      using namespace std; 
      #include <iomanip> 


    double dValue = 0.19213; 
    cout << fixed << setprecision(2) << dValue << endl 


     } 

輸出爲:

dValue = 0.19 
0

當你計算方差一樣,你可以有這樣的問題,簡單的事情......這是我的解決方案...

int getValue(double val, int precision){ 
std::stringstream ss; 
ss << val; 
string strVal = ss.str(); 
size_t start = strVal.find("."); 

std::string major = strVal.substr(0, start); 
std::string minor = strVal.substr(start + 1); 

// Fill whit zero... 
while(minor.length() < precision){ 
    minor += "0"; 
} 

// Trim over precision... 
if(minor.length() > precision){ 
    minor = minor.substr(0, precision); 
} 

strVal = major + minor; 
int intVal = atoi(strVal.c_str()); 

return intVal; 
} 

所以你將使您的calcul在整數範圍內... 例如2523.49變成了252349白色精確度的兩位數字,並且2523490白色精度爲樹數字......如果您計算平均值,例如第一個y ou轉換所有的值在整數,使求和得到雙倍的結果,所以你不積累錯誤...錯誤是像平方根和功率函數放大白衣操作...