2013-09-21 4 views
0

Я применяю метод Регулы Фальси в C++, но проблема связана с оператором ==, когда F (x3) становится 0, тогда if (fabs (f (x3)) == 0 должен остановиться и выходит из цикла, но не останавливается, почему почему? .... как вывод ниже после 12-й итерации f (x3) = 0, но если (fabs (f (x3) == 0)) не работает. loop не остановить его не должны идти на 13-й итерацииC++ == оператор не работает

float f(float x) 
{ 

float f_x; 
f_x= pow(x,3)+(3*x)-5; 
return f_x; 
} 
int main(int argc, char** argv) 
{ 

float a,b,tol,x3; 

int itr,n; 

cout << "enter the iterations"; 
cin >> itr; 
cout << "enter the interval a"; 
cin >> a; 
cout <<"enter the interval b"; 
cin >> b; 
cout << "enter the toleration"; 
cin >> tol; 

cout.setf(std::ios_base::fixed, std::ios_base::floatfield); 
cout.precision(5); 

//cout<<"fa="<<f(a)<<"fb"<<f(b); 
cout<<"n\t\ta\t\tb\t\tx3\t\tf(a)\t\tf(b)\t\tf(x3)" <<endl; 
if (f(a)*f(b)<0 && a<b) 
{ 
    for (n=0;n<itr;n++) 
    { 
     x3=a-((b-a)*f(a))/(f(b)-f(a)); 
     cout << "xx"<<fabs(f(x3)); 

     if (fabs(f(x3))==0) 
     { 
      cout << "Solution"<<fabs(f(x3)); 
       break; 
     } 
     else 
     { 
      cout<<n+1 <<"\t\t"<<a <<"\t\t"<<b <<"\t\t"<<x3<<"\t\t"<<f(a) 
      <<"\t"<<f(b)<<"\t\t"<<f(x3) <<endl; 
      if(f(x3)*f(a)<0) 
        b=x3; 
       else 
        if(f(x3)*f(b)<0) 
        a=x3; 
     } 
    } 
} 
else 
    cout<< "No Solution Exist"; 

return 0; 

}

ВЫВОД

введите iterations13

введите интервал a1

введите интервал b2

вводить toleration1

**n a   b    x3   f(a)   f(b)   f(x3)** 


1 1.00000 2.00000  1.10000  -1.00000  9.00000  -0.36900 

2 1.10000 2.00000  1.13545  -0.36900  9.00000  -0.12980 

3 1.13545 2.00000  1.14774  -0.12980  9.00000  -0.04487 

4 1.14774 2.00000  1.15197  -0.04487  9.00000  -0.01542 

5 1.15197 2.00000  1.15342  -0.01542  9.00000  -0.00529 

6 1.15342 2.00000  1.15391  -0.00529  9.00000  -0.00181 

7 1.15391 2.00000  1.15408  -0.00181  9.00000  -0.00062 

8 1.15408 2.00000  1.15414  -0.00062  9.00000  -0.00021 

9 1.15414 2.00000  1.15416  -0.00021  9.00000  -0.00007 

10 1.15416 2.00000   1.15417 -0.00007  9.00000  -0.00003 

11 1.15417 2.00000   1.15417 -0.00003  9.00000  -0.00001 

12 1.15417 2.00000   1.15417 -0.00001  9.00000  0.00000 

13 1.15417 2.00000   1.15417 -0.00000  9.00000  0.00000 
+0

Это может быть очень маленькое значение, не будучи еще ноль (и вы не увидите его в печати). Можете ли вы попробовать изменить условие от «== 0» до « Leeor

+0

Это ужасный код. Условие, что число с плавающей запятой равно другому, вряд ли встречается с помощью вычислений. ** Никогда не делайте этого **. – Walter

ответ

1

Вопрос здесь не точность с плавающей точкой; это толерантность, которую вы готовы принять в своем результате. В большинстве случаев regula falsi приблизит вас к правильному результату, когда вы пройдете больше итераций, но это будет , а не, чтобы дать вам точный ответ. Итак, решение, которое вы должны решить, насколько близко вы хотите получить результат? Это компромисс между реальными требованиями к точности и временем, необходимым для получения результата; более высокая точность требует большего вычислительного времени. Поэтому выберите допустимый для вашей задачи толерантность и повторите цикл до тех пор, пока результат не окажется в пределах этого допуска. Если это окажется слишком медленным, вам придется увеличить допуск.

+0

вы абсолютно правы, я только что положил 0.1, и он прекратил вам большое спасибо – Artemis

3

с плавающей точкой арифметика точности ошибок, поэтому в большинстве случаев лучше чтобы не сравнивать значения с плавающей запятой напрямую, используйте epsilon:

bool float_equal(float a , float b) 
{ 
    return std::abs(a-b) < 0.001; 
} 

Обратите внимание, что в вашем случае (сравнение с нолем) точность важнее: реализации с плавающей запятой выполняются для обеспечения большей точности вокруг нуля. Таким образом, вы могли бы иметь, например, цифры, такие как 0,000000000001 или 0,0000000000000000001, которые не считаются равными нулю.

Проверить эту нить для более соображений: What is the most effective way for float and double comparison?

Кроме того, обратите внимание, что std::setprecision является манипулятором, который изменяет точность вывода (печать) операции, а не точность с плавающей точкой «система».

+1

Ум, используя диапазон ошибок, здесь уместно, потому что цикл часто не дает ровно нуля в теории, даже с неограниченным количеством итераций. Это не означает ** не означает, что сравнения всегда должны использовать диапазон.Это передовая техника и имеет существенные недостатки; в частности, 'float_equal (x, y)' является истинным, а 'float_equal (y, z)' является истинным, а не ** означает, что 'float_equal (x, y)' истинно. –

+0

@PeteBecker - это потому, что эти случаи (x vs y vs z) Я включил ссылку на поток, который об этом говорит. (В частности [этот ответ] (http://stackoverflow.com/a/77735/1609356)) – Manu343726

+1

Да, эта ссылка объясняет, что ваше утверждение «никогда не сравнивать значения с плавающей запятой напрямую» неверно. –

1

Вы уверены, что f (x3) точно равно 0, а не - скажем - 0,0000000001?

Номера с плавающей запятой могут быть очень точными около 0, иногда даже до 45 цифр после точки.

+0

Я использую cout << fabs (f (x3)), он дает мне только 0, а также я установил cout.precesion (5) до 5 десятичных знаков – Artemis

+3

В этом суть. Если вы установите точность печати на 5, вы увидите 0, когда действительное значение равно 0,000001 (и ниже). cout.precision устанавливает только точность печати, а не вычислительную точность. – CygnusX1

+0

большое спасибо 0.000001032 значение после тринадцати итераций не ноль, вау вы просто качаете – Artemis

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