2013-04-28 159 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; 

}