0

I had a prior snag with this problem that was resolved but I felt that since the nature of my new issue is not related to successful compiling, rather to actual logic of the code, that it would be acceptable to make a new topic. Here is my code so far:

#include "assign4.h"
#include <iostream>

using namespace std;

int main(int argc, char * argv[]){
   solution s;
   double root;

   cout << "Enter interval endpoints: ";
   cin >> s.xLeft >> s.xRight;

   cout << "Enter tolerance: ";
   cin >> s.epsilon;

   root = s.bisect (s.xLeft, s.xRight, s.epsilon, &solution::f, s.error);

   if (!(s.error))
      cout << "Root found at " << root << "\nValue of f(x) at root is: " << s.f(root) << "\n";
   else {
      cout << "The solution of a quadratic equation with coefficients: " << endl;
//      cout << "a = " << a << ", b = " << b << ", c = " << c << endl;
      cout << "has not been found." << endl;
   }
   return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "assign4.h"
#include <iostream>
#include <math.h>

using namespace std;

 double solution::bisect (double xLeft, double xRight, double epsilon, double (solution::*f)(double), bool& error) {
   double xMid;
   double fLeft, fRight;
   double fMid;

   fLeft = (this->*f)(xLeft);
   fRight = (this->*f)(xRight);

   error = (fLeft * fRight) < 0;
   if (error)
       return -999.0;

   for (double i = 0; i < 20; i++) {
      xMid = (xLeft + (xLeft + 1.0)) / 2.0;
      fMid = (this->*f)(xMid);

      if (fLeft * fMid > 0.0) {
         xLeft = xMid + 0.5;
         xRight = xLeft + 1.0;
         fLeft = fMid;
      }
      else if (fLeft * fMid < 0.0){
         xRight = xMid;
         fRight = fMid;
      }
      else {
         return xMid;
      }

      cout << "New Interval is [" << xLeft << ", " << xRight << "]" << endl;
   }

   return (xLeft + xRight) / 2.0;
}

double solution::f (double x) {
   return ((1 * pow(x,2.0)) + (5 * x) + 2);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef ASSIGN4_H
#define ASSIGN4_H

class solution {

public:
   double xLeft, xRight;
   double epsilon;
   bool error;

   double bisect(double, double, double, double (solution::*f)(double), bool&);
   double f(double);
};
#endif // ASSIGN4_H

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

My goal with this assignment is to find any roots should they exist. My issue is that every bisection example I have found only talks about how to find a single root at once. The interval I am to use is [-10.0, 10.0] and eventually I am going to receive coefficients of the equation passed via an array encapsulated in a structure, but for now I have hard coded the coefficients.

So my problem is that I can currently get with 0.2 of the first root for the equation I have hard coded (x^2 + 5x + 2) but I am uncertain of how to step past that root and keep searching for another root up until the end of my interval. I am also unsure of how to accurately hit the root and not be marginally off.

Apologies for the wall of text and any help is appreciated! :)

Dazed_and_confused
  • 2,065
  • 2
  • 14
  • 10
  • Should this algorithm work with every function? Sorry: Haven't read the header. It should only work for quadratic functions. – OnWhenReady Apr 16 '14 at 17:28
  • It should only work for a quadratic equation but yes it should work for any quadratic. I just wanted to get results for an equation whose roots I already knew first. – Dazed_and_confused Apr 16 '14 at 17:30
  • Well .. quadratic function can have at most 2 roots. So if you found one, the other possible root can only be right of the first or left. So you only have to apply your bisectioning to [left, first_root[ and ]first_root, right]. – OnWhenReady Apr 16 '14 at 17:37
  • root = s.bisect (s.xLeft, s.xRight, s.epsilon, &solution::f, s.error); rootLeft = s.bisect (root, s.xRight, s.epsilon, &solution::f, s.error); rootRight = s.bisect (s.xLeft, root, s.epsilon, &solution::f, s.error); So Something like that? – Dazed_and_confused Apr 16 '14 at 17:46
  • Yes ... this should work – OnWhenReady Apr 16 '14 at 17:53
  • Well I added that to my test client file and it just spat out the same root three times. There must be something wrong with my logic in the bisect() function that I am not seeing. – Dazed_and_confused Apr 16 '14 at 18:02

1 Answers1

0

You can input the interval such that it includes both the roots. Then call bisect twice -- once for the lower root and once for the higher root.

 int main(int argc, char * argv[]){
    solution s;
    double root;

    cout << "Enter interval endpoints: ";
    cin >> s.xLeft >> s.xRight;

    cout << "Enter tolerance: ";
    cin >> s.epsilon;

    double xMid = 0.5*(s.xLeft + s.xRight);
    root = s.bisect (s.xLeft, xMid, s.epsilon, &solution::f, s.error);
    if (!(s.error))
       cout << "Root found at " << root << "\nValue of f(x) at root is: " << s.f(root) << endl;
    else
    {
       cout << "The solution of a quadratic equation with coefficients: " << endl;
       cout << "has not been found." << endl;
    }

    root = s.bisect (xMid, s.xRight, s.epsilon, &solution::f, s.error);
    if (!(s.error))
       cout << "Root found at " << root << "\nValue of f(x) at root is: " << s.f(root) << endl;
    else
    {
       cout << "The solution of a quadratic equation with coefficients: " << endl;
       cout << "has not been found." << endl;
    }


    return 0;
 }
R Sahu
  • 204,454
  • 14
  • 159
  • 270