цикл пока не завершается должным образом

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

#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 conditiondouble 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

Разве последнее утверждение не должно возвращать ложь? Т.е. не должен ли цикл завершаться при 24,8?

2

Решение

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

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";
}
3

Как сказал @Kerrek SB, double арифметика «не точна».

Точнее, 0.2 не может быть представлен именно с точки зрения double, Это на самом деле что-то вроде 0.1999999..., Потому что 0,2 равно 1/5, тогда как 1/5 — это бесконечная дробь в двоичном представлении. (Как и 1/3 — это бесконечная дробь в десятичном представлении).

0

вы можете использовать double с плавающим приведением в цикле, или вы можете создать свой собственный тип double с пользовательским < оператор

#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;

}
0
По вопросам рекламы [email protected]