View on GitHub

computational-mathematics

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

Routine Name: Secant

Author: Christopher Johnson

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

Declared in “secant.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. Includes safety features such as checking for division by zero and maximum iteration limit.

Input: Doubles x0 and x1 are initial guesses at location of the value. Function f(x) is the function for which a root is to be found. Integer maxiter give a user defined maximum number of iterations. Default to 100 if not given. 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 notConvergentException if the method fails to converge within tol precision in given number of iterations.

Usage/Example:

In order to call the method secant, 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 << "secant estimate of root of f(x) is " << safeNewton(x-.25,x+.25,f,fprime) << std::endl;

Output from the lines above:

secant estimate of root of f(x) is 1.35881e-08
secant estimate of root of f(x) is 1.25664
secant estimate of root of f(x) is 3.14159

It may be noted that fprime(0)=0 and this should cause the method to fail. The method corrects for this by setting the would-be zero value to tol, allowing divion to proceed. The calculated value is within the specified precision of zero. Function f() has roots at x = k*pi/10, making the other calculated roots correct.

Implementation/Code: The following is the code for secant(x0,x1,f(),maxiter,tol)

double secant (double x0, double x1, double (*f)(double),
    int maxiter = 100, double tol=pow(10,-8))
{
    double err = 10*tol;
    double f0,f1;
    while (err>tol and --maxiter>0)
    {
        f0 = f(x0);
        f1 = f(x1);
        double fdiff = f1-f0;
        if (std::abs(fdiff) == 0)
        {
            fdiff = tol;
        }
        double x2 = x1 - f1*(x1-x0)/fdiff;
        x0=x1;
        x1=x2;
        err = std::abs(x1-x0);
    }
    if(maxiter == 0)
    {
        throw notConvergent;
    }
    return x1;
}

Last Modified: October/2017