2013-04-28 199 views
2

我懷疑這可能有一些做,因爲我用雙打來控制循環終止舍入誤差,但我想真正瞭解發生了什麼事情while循環不會終止正確

#include<iostream> 

using namespace std; 

int main() 
{ 
    double h = 0.2; // stepsize                                          
    double t_0 = 1; 
    double t_n = 25; 
    double y_0 = 1; // initial condition                                        


    double t = t_0; 
    while(t < t_n) 
    { 
     cout << "t: " << t << endl; 
     cout << "(t < t_n): " << (t < t_n) << endl; 
     t += h; 
    } 
} 

輸出的最後幾行是

t: 24.4 
(t < t_n): 1 
t: 24.6 
(t < t_n): 1 
t: 24.8 
(t < t_n): 1 
t: 25 
(t < t_n): 1 

應該不是最後陳述返回false?也就是說,循環不應終止@ 24.8?

回答

3

這不工作的原因是0.2不能精確地表示在float中,因爲它的小數部分不是兩個負冪的精確和。如果您嘗試使用不同的號碼,例如0.25,則代碼將起作用,因爲0.252^-2

+0

所以即使「25」被打印到屏幕上,它實際上是24.99內部的東西嗎?另外,你會如何建議終止這樣一個循環,知道你不能退出使用0.2?並且謝謝! – bcf 2013-04-28 21:30:41

+0

@大衛正確,你得到的數字非常接近'25'(24.9 ...和大量的9),所以'printf'將它打印爲'25'。 – dasblinkenlight 2013-04-28 21:38:03

3

你是對的,double不是一個確切的類型,你不能指望確切的結果。 (典型的例子是0.1 + 0.1 + 0.1是不一樣0.3;它可以是更大或更小)。如果可行的,更喜歡定點積分算術:

for (int i = 10; i < 250; i += 2) 
{ 
    double t = i/10.0; 
    std::cout << "t: " << t << "\n"; 
} 
+0

有沒有糾正這一標準的方式實例化自己的雙類型?我唯一能想到的就是將「h」值乘以10的適當冪(所以在這種情況下,X = 10時h = 0.2)......如果這樣做,那麼我需要將hX10投射到詮釋?謝謝! – bcf 2013-04-28 21:35:56

0

像@Kerrek SB說的,double算術是「不確切」。

更準確地說,0.2不能用double來精確表示。它其實就像0.1999999...。因爲0.2等於1/5,而1/5是二進制表示中的無限分數。 (像1/3是十進制表示中的無限分數)。

0

您可以使用雙與環中的浮動鑄造或您可以用自定義<操作

#include <iostream> 

using namespace std; 



class _double 
{ 
    private : 
    double d ; 

    public : 
    _double(double d) { this->d = d ;} 
    double get() { return d ;} 

_double &operator+=(_double &a) 
    { 
     this->d+=a.get(); 
     return *this; 
    } 

void display(ostream &out) 
    { 
    cout << this->d ; 
    } 
}; 

bool operator<(_double &a,_double &b) 
    { 
     if ((float) a.get() < (float) b.get() ) 
     return true ; 
     return false ; 
    } 



ostream& operator<<(ostream& out, _double & a) 
{ 
    a.display(out) ; 
    return out; 
} 

int main() 
{ 
    double h = 0.2; // stepsize 
    double t_0 = 24; 
    int t_n = 25.; 
    double y_0 = 1; // initial condition 

    _double d1(25); 
    _double d_t(24); 
    _double d_h(0.2); 


cout << endl << " =========== First Method ============== " << endl ; 


    double t = t_0; 
    while((float) t<(float) t_n) 
    { 
     cout << "t: " << t<< endl; 
     cout << "(t < t_n): " << (t < t_n) << endl; 
     t += 0.2; 
    } 


    cout << " out of loop t: " << t << endl; 
    cout << "out of loop -> (t < t_n): " << (t < t_n) << endl; 

    cout << " =========== Second Method ============== " << endl ; 


     while(d_t< d1) 
    { 
     cout << "t: " << d_t<< endl; 
     cout << "(t < t_n): " << (d_t < d1) << endl; 
     d_t += d_h; 
    } 



    cout << "out of loop t: " << t << endl; 
    cout << "out of loop -> (t < t_n): " << (t < t_n) << endl; 
    return 0; 

}