ROOTS OF NONLINEAR EQUATIONS
4.2 AN ALGORITHM COMBINING BISECTION AND THE SECANT RULE
deal with unfavorable circumstances, the code interchanges the values of B and C as necessary so that |f(B)| < |f(C)| holds. If at any time the computed f(B) is zero, the computation is terminated and B is reported as a root.
The convergence test is a mixed relative-absolute error test. Two parameters AB- SERR and RELERR are input and it is asked of each iterate whether
(4.13) For reasons discussed in Chapter 1, the code will not permit RELERR to be smaller than 10 units of roundoff, nor ABSERR to be zero. However, to understand what the test means, first suppose that RELERR is zero. The test is then asking if an interval believed to contain a root has a length no more than 2 × ABSERR. If so, the midpoint M is no farther than ABSERR from a root and this is a pure absolute error test on M as an approximate root. However, it is believed that the quantity B reported as the answer is closer to a root than M is. Even if it is not, the test implies that B is within 2 × ABSERR of a root. Similarly, if the parameter ABSERR is zero and if the test were
the test would be a pure relative error test for the approximate root M. Because it is believed that B is a better approximate root, it is used in the test rather than M. The
fzero.m function in MATLAB has a similar, but somewhat simpler, test. The codes in the NAG and lMSL libraries have convergence tests that are broadly similar, but they also test the size of the residual and convergence can occur either because the root has been located to a specified accuracy or because the magnitude of the residual is smaller than a specified value.
Unless there is a reason to do otherwise, Zero uses the secant rule. A variable A is initialized to C. The two variables A, B are the two iterates used by the secant rule to calculate
A danger with the secant rule (and Newton’s method) is an interpolant that is horizontal or nearly so. The extreme case is a division by zero in this formula. This danger is avoided by requiring D to lie in the interval [B,C] known to contain a root and checking this without performing the division. Pursuing the tactic further, the code requires that D lie in [B,M] on the grounds that B ought to be a better approximation to the root than C, so if the secant rule is working properly, D ought to be closer to B than to C. If D does not lie in [B,M], the midpoint M is used as the next iterate.
The performance of the code can be improved in some circumstances by selecting an iterate in a different way. If D is too close to B, a better tactic is to move a minimum distance away from B. The quantity max[ABSERR, |B| × RELERR] is called TOL in the code. If |D - B| < TOL, then the value B + TOL × sign(C - B) is used instead of D. This choice cannot result in an iterate outside the interval [B,C] since |B - C| > 2 × TOL (or else the error test would have been passed). If the root a is further from
B than TOL, the iterate chosen in this way is closer to the root than D. If it is closer, this iterate and B will bracket the root and the code will converge at the next test on the error because the length of the bracket is TOL.
There are circumstances in which the current iterate B is converging to a root, but the end point C is fixed. Because convergence is judged by the length of the interval [B,C] and because the rate of convergence of the secant rule depends on using values from the neighborhood of the root, the code monitors the length of the interval. If four iterations have not resulted in a reduction by a factor of l/8, the code bisects three times. This guarantees that the code will reduce the length of an interval containing a root by a factor of l/8 in a maximum of seven function evaluations.
In summary, if the value D of the secant rule lies outside [B,M] or if the overall reduction in interval length has been unsatisfactory, the code bisects the interval. If D is too close to B, a minimum change of TOL is used. Otherwise D is used. After deciding how to compute the next iterate, it is formed explicitly and replaces B. If f(B) = 0, the code exits. Otherwise, quantities are updated for the next iteration: the old B replaces A. The old C is kept or is replaced by the old B, whichever results in f(B)f(C) < 0.
If the code is given normal input [f(x) continuous, f(B)f(C) < 01, then on nor- mal return, either the computed f(B) = 0, or the computed f(B) and f(C) satisfy f(B)f(C) < 0, |f(B)| < |f(C)| and the output values of B and C satisfy (4.13). In the latter case there is either a root of f(x) in the interval [B,C] or else one of the end points is so close to a root that the sign has been computed incorrectly in the working precision.
EXERCISES
4.9 The algorithm described combining the bisection method with the secant method is very efficient. Sup- pose that the initial B and C satisfy |B - C| = 1010, and a root is sought with an absolute error of at most 1 0- 5
(a) How many function evaluations does the bisec- tion method use?
(b) What is the maximum number of function evalu- ations needed by the combined algorithm?
4.3
ROUTINES FOR ZERO FINDING
The algorithm of the preceding section has been implemented in a routine called Zero designed to compute a root of the nonlinear equation F(x) = 0. A typical invocation of Zero in C++ is
flag = Zero(f, b, c, abserr, relerr, residual); in FORTRAN it is
CALL ZERO(F, B, C, ABSERR, RELERR, RESIDL, FLAG) and