//////////////////////////////////////////////////////////////////////////////// // File: secant_method.c // // Routines: // // double Secant_Method // //////////////////////////////////////////////////////////////////////////////// #include // required for fabs() //////////////////////////////////////////////////////////////////////////////// // double Secant_Method( double (*f)(double), double a, double b, // // double tolerance, int max_iteration_count, int *err) // // // // Description: // // Estimate the root (zero) of f(x) using the secant method where 'a' // // and 'b' are two initial estimates. The process terminates successfully// // when the change in the estimate of the root is less than 'tolerance' // // or unsuccessfully when the number of iterations reaches 'max_iteration_// // count' or if an attempt is made to divide by zero. // // // // The secant method uses two points on the curve f(x) to estimate the // // root as the intersection of the x-axis with the line joining the // // two points (the secant). The process then replaces the oldest of the // // two estimates with the newest estimate. The process continues until // // the distance between the two estimates is less than the tolerance. // // The process can fail if there is a local maximum or minimum near the // // the root and is sensitive to having good initial estimates. If there // // is a local maximum or minimum in the neigborhood of the root, the // // return value should be verified before use. The secant method is // // similar to the Newton-Raphson method in which the derivative is // // replaced by a numerical estimate of the derviative. // // // // Arguments: // // double *f Pointer to function of a single variable of type // // double. // // double a Initial estimate. // // double b Initial estimate. // // double tolerance Desired accuracy of the zero, tolerance > 0. // // int max_iteration_count Maximum allowable number of iterations. // // int *err 0 if successful, -1 if not, i.e. the iteration // // count meets or exceeds the max_iteration_count, // // -2 if an attempt is made to divide by zero. // // // // Return Values: // // A zero somewhere in a neighborhood of a and b. // // // // Example: // // { // // double f(double), zero, a, b, tolerance = 1.e-6; // // int max_iteration = 10; // // int err; // // // // (determine nearby values a and b of a zero) // // zero = Secant_Method( f, a, b, tolerance, max_iterations, &err); // // ... // // } // // double f(double x) { define f } // //////////////////////////////////////////////////////////////////////////////// // // double Secant_Method( double (*f)(double), double a, double b, double tolerance, int max_iteration_count, int *err) { double fa = (*f)(a), fb = (*f)(b), delta; int i; *err = 0; for (i = 0; i < max_iteration_count; i++) { // Insure that the f(b) has smaller magnitude than f(a). // if ( fabs(fa) < fabs(fb) ) { delta = a; a = b; b = delta; delta = fa; fa = fb; fb = delta; } // If an attempt to divide by zero, return with an error code -2. // if ( fb == fa ) { *err = -2; return 0.0; } // Estimate the location of the root relative to b. // delta = fb * (a - b) / (fb - fa); // If the location of the root relative to b is less than // // the tolerance, return the estimate of the root. // if ( delta == 0.0 ) return b; if ( fabs(delta) < tolerance ) return b + delta; // Otherwise, update the estimate of the root. // a = b + delta; fa = (*f)(a); } *err = -1; return a; }