Thread: Help!Bisection method in C++

  1. #1
    Registered User
    Join Date
    Nov 2011
    Location
    Harrison, New Jersey, United States
    Posts
    9

    Question Help!Bisection method in C++

    I am working on bisection method to calculate interest rate in C++,but there is some problems with my codes:the root is always 7.62939E-06.Please help me figure out why my program always fails.

    The header file: (hasRoot is a class which has only one member function f:fv+pv*pow(1+rate,nPer)+pmt/rate*(pow(1+rate,nPer)-1)).

    Code:
    #include "hasRoot.h"class rootFinder{
    private:
    double tol; 
    /*the allowed difference between the calculated root and the actual root.*/
    int MaxIter; //the maximum iteration times
    public:
    rootFinder(double a=0.00001,int b=20000){
    tol=a;
    MaxIter=b;
    }
    double functionsolver(hasRoot&);
    };
    The implementation part:

    Code:
    #include "rootFinder.h"
    #include <cmath>
    
    double rootFinder::functionsolver(hasRoot& objecttobesolved){
    int counter=1; //Counts the iteration times.
    double left=0;
    double right=1;
    for (;counter<=MaxIter;counter++){
         double mid=(left+right)/2.0;
         if( fabs(objecttobesolved.f(mid))<=tol || (right-left)<tol){
         return mid;
         break;
         }
        if( objecttobesolved.f(mid)*objecttobesolved.f(right)>0)
              right=mid;
        if( objecttobesolved.f(mid)*objecttobesolved.f(right)<0)
              left=mid;
      }
    }
    Everytime I run it,no matter what are the values of pv(present value),fv(future value),pmt(payment) and nPer(number of Periods),I always get the same result 7.62939E-06.

  2. #2
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    A few things:
    There isn't any point in having a break after a return as it can never get to the break. The compiler should be warning you about unreachable code. Just delete the break.

    This expression is written twice:
    Code:
    objecttobesolved.f(mid)*objecttobesolved.f(right)
    Although compilers can often perform common subexpression elimination, in this case that most probably cannot occur. The compiler cant prove that the function f has no side effects. In fact, you didn't even provide the function f here so we can't even see what it does! Summarising what it does is not the same thing.
    Furthermore, I can't understand why you are multiplying the result of f(mid) and f(right) to begin with. It most certainly doesn't perform bisection properly. Also note that multiplying two negatives results in a positive, thus why it appears to be going left every time.

    At the moment is that if the above expression happened to evaluate to exactly 0, then if would neither alter right, nor left. What you should do to fix that is to turn the last if into a plain old else. This also means that you don't need to calculate the expression above twice.

    Your MaxIter variable is redundant. You don't need to stop either when the right-left < tol and when counter > MaxIter. Well that is once you fix the bug I just mentioned by using an else. At the moment it's the only thing stopping an infinite loop.
    Last edited by iMalc; 12-30-2011 at 06:43 PM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  3. #3
    Registered User
    Join Date
    Nov 2011
    Location
    Harrison, New Jersey, United States
    Posts
    9
    Thank you very much for offering me suggestions.But after I fixed the codes according to your suggestions,I still got 7.62939E-06.
    As to "why multiply f(mid) by f(right)",I think it is the principle of bisection method because my professor told me to do so.Maybe you could check it by yourself.
    Finally I show the function f:

    Code:
    double f(double exprate) const{
         double trialvalue;
         trialvalue=fv+pv*pow(1+exprate,nPer)+pmt/exprate*(pow(1+exprate,nPer)-1);
         return trialvalue;
    }

  4. #4
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    After looking into it further, yes the multiplication probably will do what you want, but it's certainly not the clearest way of doing it.

    Do you even know if the function you're providing has a root between 0 and 1? If it doesn't then that would explain the output.
    Can you modify the code to output the values of f as it goes so we can see what's going on?
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  5. #5
    Registered User
    Join Date
    Nov 2011
    Location
    Harrison, New Jersey, United States
    Posts
    9
    Because the root I am looking for is actually interest rate,I am sure the root is between 0 and 1.
    Could you clarify the meaning of your last sentence?Do you mean that I should try to modify the codes of f?

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    It would probably be better to modify the code inside functionsolver
    Code:
        cout << "mid=";
        cout << mid;
        cout << ", f(mid)=";
        cout << objecttobesolved.f(mid);
        cout << " right=";
        cout << right;
        cout << ", f(right)=";
        cout << objecttobesolved.f(right) << endl;
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  7. #7
    Registered User
    Join Date
    Nov 2011
    Location
    Harrison, New Jersey, United States
    Posts
    9
    Oh yeah!Thanks to those output codes,I figured out the reason!It involves the overwriting of virtual functions.
    Thank you very much!Happy new year!
    Last edited by cxwcxw2001; 12-31-2011 at 09:07 AM.

  8. #8
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Awesome. Same to you!
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Bisection with typedef declaration
    By idecline in forum C Programming
    Replies: 13
    Last Post: 11-21-2010, 11:57 AM
  2. bisection method
    By swty_todd in forum C Programming
    Replies: 4
    Last Post: 02-08-2009, 12:33 AM
  3. bisection method
    By bar5037 in forum C++ Programming
    Replies: 13
    Last Post: 10-30-2007, 04:26 PM
  4. Bisection Method function value at root incorrect
    By mr_glass in forum C Programming
    Replies: 3
    Last Post: 11-10-2005, 09:10 AM
  5. problem with the bisection method
    By dionys in forum C Programming
    Replies: 1
    Last Post: 04-01-2004, 04:19 PM