2017-10-10 67 views
1

當我編寫一個需要時間數組的ODE解算器時,我最終遇到了以下非常奇怪的行爲。以下代碼應清楚地重現問題。<=和==運算符不能正常工作以結束循環

#include <iostream> 
using namespace std; 

int main() { 
    double t = 0.0; 
    for (t = 0.0; t <= 1.00; t += 0.01) { 
     cout << t << " "; 
    } 
    cout << endl; 

    cout << "t = "<< t << " and t <= 1.00? " << (t <= 1.00) << endl; 
    double c = 1.00; 
    cout << "c = "<< c << " and c <= 1.00? " << (c <= 1.00) << endl; 
    cout << "t == 1.00? " << (t == 1.00) << " and c == 1.00? " << (c == 1.00) << endl; 
    return 0; 
} 

這給出以下輸出:

0 0.01 0.02 0.03 0.04 ... 0.97 0.98 0.99 
t = 1 and t <= 1.00? 0 
c = 1 and c <= 1.00? 1 
t == 1.00? 0 and c == 1.00? 1 

我的問題是:爲什麼(噸< = 1.00)和(T == 1.00)返回false而噸顯然應該等於1且t是雙重類型的?

我真的不能避免這個問題的原因在我真正的代碼,我的丁字步不硬編碼等等

謝謝你提前。

編輯:謝謝你的答案。這確實是0.01等的二進制表示的問題不是確切的,而是有一定的舍入誤差。這個量表真的是由程序中的其他物理量來執行的。另一個我在其他地方得到的答案/提示是,如果需要與浮點成員一起工作,總是需要忍耐。在這種情況下,當使用我的應用程序所需的精度爲h的變量時,「t < = 1.00」可能變爲「t < 1.00 + 0.01/2」或更一般的「t < 1.00 + h/2」。

+0

@ tobi303:它應該產生錯誤。如果它是真的,循環不會停止。 (至於'c <= 1.00'是真的,那是因爲'c!= t'。) – user2357112

+0

@ user2357112是的,我剛剛意識到我的愚蠢。所以當考慮到漂浮物不會很好地漂移時,它就像預期的那樣 – user463035818

+0

嘗試在'main'的開始處添加'cout.precision(17);'問題將變得明顯(或者提出更相關的問題)。您只顯示幾個小數位,可以累計累積誤差。 –

回答

2

浮點算術不能像你所期望的那樣工作。

罪魁禍首是你在for循環條件:

t <= 1.00 

tdouble並因此增加100倍0.01〜0.00是不完全等於1.00但大約相等於它。

可以解決這個問題的方法:

int t; 
for (t = 0; t <= 100; t++) { 
    std::cout << static_cast<double>(t)/100 << " "; 
} 

然後:

std::cout << "t = "<< static_cast<double>(t)/100 << " and t <= 1.00? " << (static_cast<double>(t)/100 <= 1) << std::endl;