2013-04-28 5 views
2

я подозреваю, что это может иметь что-то делать с ошибками округления, поскольку я использую двойники контролировать окончание цикла, но я хотел бы, чтобы действительно знать, что происходит нав то время как цикл не завершается должным образом

#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 

не следует последнее утверждение вернуться ложным? I.e., не должен ли цикл прекратить @ 24.8?

ответ

3

Причина, это не работает в что 0.2 не может быть представлен точно в float, поскольку его дробная часть не является точной суммой отрицательных степеней двух. Если вы попробуете его с другим номером, скажем, 0.25, код будет работать, потому что 0.25 - 2^-2.

+0

Итак, хотя «25» печатается на экране, это на самом деле что-то вроде 24.99 внутри? Кроме того, как бы вы порекомендовали прекратить такой цикл, зная, что вы не можете отказаться от использования 0.2? И спасибо!! – bcf

+0

@David Правильно, число, которое вы получаете, очень близко к '25' (24,9 ... и много девяток), поэтому' printf' печатает его как '25'. – dasblinkenlight

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 в Int? Благодаря! – bcf

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; 

} 

 Смежные вопросы

  • Нет связанных вопросов^_^