2010-12-02 34 views
2

我遇到了浮點算術的一些問題,並不準確。我試圖根據加權公式計算得分,其中每個輸入變量的重量大約是下一個重要變量的20倍。然而,輸入是實數,所以我最終使用了double來存儲結果。以下代碼存在丟失E1和E2之間差異的問題。如何解決C++中浮點運算的舍入問題?

此代碼對性能非常敏感,所以我需要爲這個問題找到一個有效的答案。我想我的輸入乘以一百,然後用一個int(因爲這足夠精確,我認爲),但我懷疑這是最好的解決方案,因此是一個問題。

#include <iostream> 

int main() 
{ 
    double score1, score2; 
    float a = 2.75 ; 
    float b = 5.25 ; 
    float c = 5.25 ; 
    float d = 2.75 ; 
    float E1 = 3 ; 
    float E2 = 6 ; 

    score1 = 20 * b - 1 * a + 0.05 * d /* - 0.0025 * c*/ + 0.0001 * E1 ; 
    score2 = 20 * b - 1 * a + 0.05 * d /* - 0.0025 * c*/ + 0.0001 * E2 ; 

    std::cout << score1 << std::endl; 
    std::cout << score2 << std::endl; 

    std::cin.get(); 
    return 0; 
} 

//ouputs: 
//102.388 
//102.388 
+0

浮點是有限的,即它不能代表所有的浮點數,有很多關於它的信息的。 – Drakosha 2010-12-02 20:20:51

+1

你可以使用雙。限制自己漂浮的限制效用是有限的(除了存儲空間,除非你處於非常特殊的情況下不應該是個問題)。 – 2010-12-02 20:24:14

回答

4
  1. 你是不是輸出整個值,使用cout << setprecision(number_of_digits) << score1 << endl;
  2. 多少有效的數字,你在你的分數計算需要什麼?
+0

謝謝,設置更高的精度我現在看到正確的值,這是否意味着我的代碼實際上按照預期的方式工作,比較像'if(score1 nus 2010-12-02 20:25:45

+0

這樣的分數那麼,是的,比較兩個浮點數將比較它們的值。 – 2010-12-02 20:31:02

3

我想用一百年我輸入相乘,然後使用一個int(因爲這將是足夠的,我認爲準確),但我懷疑這是最好的解決方案

鑑於你已經展示的價值觀,我會說它是。

+0

實際上,將輸入乘以100將不起作用 - 即使輸入是整數,也不是所有計算都會導致整數。您必須將輸入乘以10000或1000000並更改計算中的常量。 – 2010-12-02 20:21:47

1

http://ideone.com/qqTB3向您顯示差異不會丟失,但實際上與您預期的一樣大(達到浮點精度,即雙精度值的15位十進制數)。

1

讓我們來看看發生了什麼事在此代碼:

score1 = 20 * b - 1 * a + 0.05 * d /* - 0.0025 * c*/ + 0.0001 * E1 ; 

// Multiplication division happens first: 

float tmp1 = static_cast<float>(20) * b;  // 20 cast to float. 
float tmp2 = static_cast<float>(1) * a;  // 1 cast to float. 
double tmp3 = 0.05 * static_cast<double>(d); // d converted to double as 0.05 is double 
double tmp4 = 0.0001 * static_cast<double>(E1);// E1 cast to double as 0.0001 is double 

// Addition and subtraction now happen 
float tmp5 = tmp1 - tmp2; 
double tmp6 = static_cast<double>(tmp5) + tmp3; // tmp5 cast to double as tmp3 is a double. 
double tmp7 = tmp6 + tmp4; 
score1  = tmp7; 

如果我們這樣做,在我們的頭腦:

tmp1 = 105.0 
tmp2 = 2.75 
tmp3 = 0.1375 
tmp4 = 0.0003 
tmp5 = 107.75 
tmp6 = 107.8875 
tmp7 = 107.8878 

精度應保持這些值:
但是,當你打印出來雙打的默認精度爲3位小數。

std::cout << 107.8878; 
> 107.888 

所以設定精度:

std::cout << std::setprecision(15) << 107.8878 << "\n"; 
> 107.8878