View on GitHub

computational-mathematics

Contains basic implementations of a number of standard procedures in scientific computing and computational mathematics.

Routine Name: bisection_newton

Author: Christopher Johnson

Language: C++. Tested with g++ compiler.

Declared in “newton.h”

Description/Purpose: This routine will approximate the a solution to the root finding problem f(x)=0, guaranteed within a user input tolerance, using the secant method.

Input: Doubles a and b are initial guesses at location of the value. Function f(x) is the function for which a root is to be found. Function fprime(x) is the derivative of f(x). Double tol dictates the required precision of an answer. Default to 1e-8 if not given.

Output: Returns a single double, giving the appoximated solution of f(x)=0. The method will instead throw a invalidIntervalException if improperly bracketed.

Usage/Example:

In order to call the method bisection_newton, a target function f(x) must first be defined. The function may then be called as follows:

double f(double x) {return 3*x*sin(10*x); }
for (int x=0; x<3; x++)
    std::cout << "bisection_newton estimate of root of f(x) is " << bisection_newton(x-.25,x+.25,f,fprime) << std::endl;

Function returns error for ranges around 0 and 2, due to improper bracketing. Output from the intial value x=1:

secant estimate of root of f(x) is 0.942478

The method is more restricted by the requirement for proper bracketing.

Implementation/Code: The following is the code for bisection_newton(a,b,f(),fprime(),tol)

inline double newtonStep (double x, double (*f)(double), double (*fprime)(double))
{
    return x - f(x)/fprime(x);
}

void bisect_step (double& a, double& b, double (*f)(double), int iterations)
{
        for(int i=0; i<iterations; i++)
        {
                double c = (a+b)*.5;
                //Divide the interval at the midpoint c
                if (f(a)*f(c)<0)
                        b=c;
                else
                        a=c;
        }
}

double bisection_newton (double a, double b, double (*f)(double),
    double (*fprime)(double), double tol=pow(10,-8))
{
    if (a>b) std::swap(a,b);
    if (f(a)*f(b)>0)
        throw invalidInterval;

    double err = tol*10;
    while (err>tol)
    {
        bisect_step(a,b,f,4);
        err = std::abs(a-b);
        double x = newtonStep((a+b)/2,f,fprime);
        if (a<=x and x<=b)
        {
            while (err>tol and a<=x and x<=b)
            {
                double x1 = newtonStep(x,f,fprime);
                err = std::abs(x1-x);
                x=x1;
            }
            if (tol>err)
                return x;
        }
    }
    return a;
}

Last Modified: October/2017