0

i am applying Regula Falsi method in C++ but the problem is with == operator when F(x3) become 0 then if (fabs( f(x3))==0 should stop and comes out from the loop but it does not stop why why why.... like output below after 12th iteration f(x3)=0 but if(fabs(f(x3)==0)) does not run. loop does not stop it should not go to 13th iteration

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;

}

OUTPUT

enter the iterations13

enter the interval a1

enter the interval b2

enter the 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
Manu343726
  • 13,969
  • 4
  • 40
  • 75
Artemis
  • 141
  • 4
  • 10
  • It could be a very small value without being zero yet (and you wont see it in the printing) - can you try changing the condition from "== 0" to " < threshold_value" (make that as small as you like) – Leeor Sep 21 '13 at 12:06
  • This is horrible code. The condition that a floating point number equals another one is hardly every met by computations. **Never do that**. – Walter Sep 21 '13 at 13:31

3 Answers3

3

Floating point arithmetic has precision errors, so in most cases is better to not compare floating point values directly, use an epsilon:

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

Note that in your case (comparison with zero) the precision is more important: Floating point implementations are dessigned to provide more precision around the zero. So you could have, for example, numbers like 0,000000000001 or 0,0000000000000000001 which are not considered equal to zero.

Check this thread for more considerations: What is the most effective way for float and double comparison?

In addition, note that std::setprecision is a manipulator which changes the precision of the output (printing) operations, not the precision of the floating-point "system".

Community
  • 1
  • 1
Manu343726
  • 13,969
  • 4
  • 40
  • 75
  • 1
    Um, using an error range is appropriate here, because the loop will often not produce exactly zero in theory, even with an unlimited number of iterations. This does **not** mean that comparisons should always use a range. That's an advanced technique, and has significant drawbacks; in particular, `float_equal(x, y)` being true and `float_equal(y, z)` being true does **not** imply that `float_equal(x, y)` is true. – Pete Becker Sep 21 '13 at 12:23
  • @PeteBecker is because that cases (x vs y vs z) I have included a link to a thread which talks about that. (Specifically [this answer](http://stackoverflow.com/a/77735/1609356)) – Manu343726 Sep 21 '13 at 12:27
  • 1
    Yes, that link explains that your assertion "never compare floating point values directly" is wrong. – Pete Becker Sep 21 '13 at 12:29
  • i have added your code but still the same case my code is bool comp(float fx) { return fabs(fx)::epsilon(); } – Artemis Sep 21 '13 at 12:30
  • @Artemis be careful, in your code you are using float, and in that code you are using double epsilon – Manu343726 Sep 21 '13 at 12:34
  • @Artemis Also note that [there is no reason to use fabs](http://stackoverflow.com/questions/3118165/when-do-i-use-fabs-and-when-is-it-sufficient-to-use-stdabs), use [std::abs()](http://en.cppreference.com/w/cpp/numeric/math/fabs). fabs() is inherited from C, which has no function overloading (The f prefix is to differentiate integer version from floating point version). In C++ std::abs() has a proper overload for floating-point numbers – Manu343726 Sep 21 '13 at 12:40
  • 1
    @Artemis - don't use anything named "epsilon". What you're looking for here is a **tolerance**, that is, you need to decide how close to 0 you want the result to be, since additional iterations will get the result **closer** to 0. To get things going, just try `0.1`; once that's working (and producing rather sloppy results), refine it. – Pete Becker Sep 21 '13 at 12:51
  • let me ask one thing how will i limit the float number upto 5 or 3 or 2 decimal digits is their any way to do this?? – Artemis Sep 21 '13 at 12:56
  • 1
    @Artemis yes: As Peter have said, you have to decide the tolerance of your comparisons. Choose a tolerance which considers floating-point numbers with differences passed the first five decimal digits are equal. That is, a tolerance of 0,000001 – Manu343726 Sep 21 '13 at 13:03
2

Are you certain f(x3) is exactly 0, and not - say - 0.0000000001 ?

Floating point numbers can be very accurate around 0, sometimes even down to 45 digits after the dot.

CygnusX1
  • 20,968
  • 5
  • 65
  • 109
1

The issue here is not floating-point precision; it's the tolerance that you're willing to accept in your result. In most cases, regula falsi will get you closer and closer to the correct result as you run through more iterations, but it will not give you the exact answer. So the decision you have to make is, how close do you want the result to be? That's a tradeoff between the real-world requirements for accuracy and the time it takes to get the result; more accuracy requires more computing time. So choose a tolerance that's acceptable for your task, and repeat the loop until the result is within that tolerance. If it turns out to be too slow, you'll have to increase the tolerance.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165