The method
Stopping condition
"we can select a tolerance \epsilon > 0 and generate c1, ..., cN until one of the following conditions is met: Unfortunately, difficulties can arise using any of these stopping criteria ... Without additional knowledge about f or c, inequality (2.2) is the best stopping criterion to apply because it comes closest to testing relative error." (Note: c has been used here as it is more common than Burden and Faire's 'p'.)
def bisect(f, a, b, tolerance): fa = f(a) fb = f(b) i = 0 stop_a = [] stop_r = [] while True: i += 1 c = a + (b - a) / 2 fc = f(c) if c < 10: # For small root if not stop_a: print(' , ' .format(i, a, b, c, b - a, (b - a) / c)) else: # large root print(' , ----- ' .format(i, a, b, c, b - a)) else: if not stop_r: print(' , ' .format(i, a, b, c, b - a, (b - a) / c)) else: print(' , ----- ' .format(i, a, b, c, b - a)) if fc 0: return , i if (b - a <= abs(c) * tolerance) & (stop_r []): stop_r = , i if (b - a <= tolerance) & (stop_a []): stop_a = , i if np.sign(fa) np.sign(fc): a = c fa = fc else: b = c fb = fc if (stop_r != []) & (stop_a != []): return [stop_a, stop_r]
print(' i a b c b - a (b - a)/c') f = lambda x: x - 0.00000000123456789 res = bisect(f, 0, 1, 5e-7) print('In steps the absolute error case gives '.format(res 1], res 0])) print('In steps the relative error case gives '.format(res 1], res 0])) print(' as the approximation to 0.00000000123456789')
i a b c b - a (b - a)/c 1 0.0000000000000000 1.0000000000000000 5.0000000000000000e-01 , 1.00e+00 2.00e+00 2 0.0000000000000000 0.5000000000000000 2.5000000000000000e-01 , 5.00e-01 2.00e+00 3 0.0000000000000000 0.2500000000000000 1.2500000000000000e-01 , 2.50e-01 2.00e+00 4 0.0000000000000000 0.1250000000000000 6.2500000000000000e-02 , 1.25e-01 2.00e+00 5 0.0000000000000000 0.0625000000000000 3.1250000000000000e-02 , 6.25e-02 2.00e+00 6 0.0000000000000000 0.0312500000000000 1.5625000000000000e-02 , 3.12e-02 2.00e+00 7 0.0000000000000000 0.0156250000000000 7.8125000000000000e-03 , 1.56e-02 2.00e+00 8 0.0000000000000000 0.0078125000000000 3.9062500000000000e-03 , 7.81e-03 2.00e+00 9 0.0000000000000000 0.0039062500000000 1.9531250000000000e-03 , 3.91e-03 2.00e+00 10 0.0000000000000000 0.0019531250000000 9.7656250000000000e-04 , 1.95e-03 2.00e+00 11 0.0000000000000000 0.0009765625000000 4.8828125000000000e-04 , 9.77e-04 2.00e+00 12 0.0000000000000000 0.0004882812500000 2.4414062500000000e-04 , 4.88e-04 2.00e+00 13 0.0000000000000000 0.0002441406250000 1.2207031250000000e-04 , 2.44e-04 2.00e+00 14 0.0000000000000000 0.0001220703125000 6.1035156250000000e-05 , 1.22e-04 2.00e+00 15 0.0000000000000000 0.0000610351562500 3.0517578125000000e-05 , 6.10e-05 2.00e+00 16 0.0000000000000000 0.0000305175781250 1.5258789062500000e-05 , 3.05e-05 2.00e+00 17 0.0000000000000000 0.0000152587890625 7.6293945312500000e-06 , 1.53e-05 2.00e+00 18 0.0000000000000000 0.0000076293945312 3.8146972656250000e-06 , 7.63e-06 2.00e+00 19 0.0000000000000000 0.0000038146972656 1.9073486328125000e-06 , 3.81e-06 2.00e+00 20 0.0000000000000000 0.0000019073486328 9.5367431640625000e-07 , 1.91e-06 2.00e+00 21 0.0000000000000000 0.0000009536743164 4.7683715820312500e-07 , 9.54e-07 2.00e+00 22 0.0000000000000000 0.0000004768371582 2.3841857910156250e-07 , 4.77e-07 2.00e+00 23 0.0000000000000000 0.0000002384185791 1.1920928955078125e-07 , ----- 2.38e-07 24 0.0000000000000000 0.0000001192092896 5.9604644775390625e-08 , ----- 1.19e-07 25 0.0000000000000000 0.0000000596046448 2.9802322387695312e-08 , ----- 5.96e-08 26 0.0000000000000000 0.0000000298023224 1.4901161193847656e-08 , ----- 2.98e-08 27 0.0000000000000000 0.0000000149011612 7.4505805969238281e-09 , ----- 1.49e-08 28 0.0000000000000000 0.0000000074505806 3.7252902984619141e-09 , ----- 7.45e-09 29 0.0000000000000000 0.0000000037252903 1.8626451492309570e-09 , ----- 3.73e-09 30 0.0000000000000000 0.0000000018626451 9.3132257461547852e-10 , ----- 1.86e-09 31 0.0000000009313226 0.0000000018626451 1.3969838619232178e-09 , ----- 9.31e-10 32 0.0000000009313226 0.0000000013969839 1.1641532182693481e-09 , ----- 4.66e-10 33 0.0000000011641532 0.0000000013969839 1.2805685400962830e-09 , ----- 2.33e-10 34 0.0000000011641532 0.0000000012805685 1.2223608791828156e-09 , ----- 1.16e-10 35 0.0000000012223609 0.0000000012805685 1.2514647096395493e-09 , ----- 5.82e-11 36 0.0000000012223609 0.0000000012514647 1.2369127944111824e-09 , ----- 2.91e-11 37 0.0000000012223609 0.0000000012369128 1.2296368367969990e-09 , ----- 1.46e-11 38 0.0000000012296368 0.0000000012369128 1.2332748156040907e-09 , ----- 7.28e-12 39 0.0000000012332748 0.0000000012369128 1.2350938050076365e-09 , ----- 3.64e-12 40 0.0000000012332748 0.0000000012350938 1.2341843103058636e-09 , ----- 1.82e-12 41 0.0000000012341843 0.0000000012350938 1.2346390576567501e-09 , ----- 9.09e-13 42 0.0000000012341843 0.0000000012346391 1.2344116839813069e-09 , ----- 4.55e-13 43 0.0000000012344117 0.0000000012346391 1.2345253708190285e-09 , ----- 2.27e-13 44 0.0000000012345254 0.0000000012346391 1.2345822142378893e-09 , ----- 1.14e-13 45 0.0000000012345254 0.0000000012345822 1.2345537925284589e-09 , ----- 5.68e-14 46 0.0000000012345538 0.0000000012345822 1.2345680033831741e-09 , ----- 2.84e-14 47 0.0000000012345538 0.0000000012345680 1.2345608979558165e-09 , ----- 1.42e-14 48 0.0000000012345609 0.0000000012345680 1.2345644506694953e-09 , ----- 7.11e-15 49 0.0000000012345645 0.0000000012345680 1.2345662270263347e-09 , ----- 3.55e-15 50 0.0000000012345662 0.0000000012345680 1.2345671152047544e-09 , ----- 1.78e-15 51 0.0000000012345671 0.0000000012345680 1.2345675592939642e-09 , ----- 8.88e-16 52 0.0000000012345676 0.0000000012345680 1.2345677813385691e-09 , ----- 4.44e-16 In 22 steps the absolute error case gives 0.000000238418579102 In 52 steps the relative error case gives 0.000000001234567781 as the approximation to 0.00000000123456789
print(' i a b c b - a (b - a)/c') res = bisect(fun, 1234550, 1234581, 5e-7) print('In %2d steps the absolute error case gives %20.18F' % (res 1], res 0])) print('In %2d steps the relative error case gives %20.18F' % (res 1], res 0])) print(' as the approximation to 1234567.89012456789')
i a b c b - a (b - a)/c 1 1234550.0000000 1234581.0000000 1.2345655e+06 , 3.10e+01 2.51e-05 2 1234565.5000000 1234581.0000000 1.2345732e+06 , 1.55e+01 1.26e-05 3 1234565.5000000 1234573.2500000 1.2345694e+06 , 7.75e+00 6.28e-06 4 1234565.5000000 1234569.3750000 1.2345674e+06 , 3.88e+00 3.14e-06 5 1234567.4375000 1234569.3750000 1.2345684e+06 , 1.94e+00 1.57e-06 6 1234567.4375000 1234568.4062500 1.2345679e+06 , 9.69e-01 7.85e-07 7 1234567.4375000 1234567.9218750 1.2345677e+06 , 4.84e-01 3.92e-07 8 1234567.6796875 1234567.9218750 1.2345678e+06 , 2.42e-01 ----- 9 1234567.8007812 1234567.9218750 1.2345679e+06 , 1.21e-01 ----- 10 1234567.8613281 1234567.9218750 1.2345679e+06 , 6.05e-02 ----- 11 1234567.8613281 1234567.8916016 1.2345679e+06 , 3.03e-02 ----- 12 1234567.8764648 1234567.8916016 1.2345679e+06 , 1.51e-02 ----- 13 1234567.8840332 1234567.8916016 1.2345679e+06 , 7.57e-03 ----- 14 1234567.8878174 1234567.8916016 1.2345679e+06 , 3.78e-03 ----- 15 1234567.8897095 1234567.8916016 1.2345679e+06 , 1.89e-03 ----- 16 1234567.8897095 1234567.8906555 1.2345679e+06 , 9.46e-04 ----- 17 1234567.8897095 1234567.8901825 1.2345679e+06 , 4.73e-04 ----- 18 1234567.8899460 1234567.8901825 1.2345679e+06 , 2.37e-04 ----- 19 1234567.8900642 1234567.8901825 1.2345679e+06 , 1.18e-04 ----- 20 1234567.8901234 1234567.8901825 1.2345679e+06 , 5.91e-05 ----- 21 1234567.8901234 1234567.8901529 1.2345679e+06 , 2.96e-05 ----- 22 1234567.8901234 1234567.8901381 1.2345679e+06 , 1.48e-05 ----- 23 1234567.8901234 1234567.8901308 1.2345679e+06 , 7.39e-06 ----- 24 1234567.8901234 1234567.8901271 1.2345679e+06 , 3.70e-06 ----- 25 1234567.8901234 1234567.8901252 1.2345679e+06 , 1.85e-06 ----- 26 1234567.8901243 1234567.8901252 1.2345679e+06 , 9.24e-07 ----- 27 1234567.8901243 1234567.8901248 1.2345679e+06 , 4.62e-07 ----- In 27 steps the absolute error case gives 1234567.890124522149562836 In 7 steps the relative error case gives 1234567.679687500000000000 as the approximation to 1234567.89012456789
Convergence Tests, RTOL and ATOL Tolerances are usually specified as either a relative tolerance RTOL or an absolute tolerance ATOL, or both. The user typically desires that , True value -- Computed value , < RTOL*, True Value, + ATOL (Eq.1) where the RTOL controls the number of significant figures in the computed value (a float or a double), and a small ATOL is a just a "safety net" for the case where True Value is close to zero. (What would happen if ATOL = 0 and True Value = 0? Would the convergence test ever be satisfied?) You should write your programs to take both RTOL and ATOL as inputs."
IEEE Standard-754 for Computer Arithmetic
Algorithm
import numpy as np import math def bisect(f, a, b, tol, bound=9.8813129168249309e-324): ############################################################################E # input: Function f, # endpoint values a, b, # tolerance tol, (if tol = 5e-t and bound = 9.0e-324 the function # returns t significant digits for a root between the # minimum normal and the maximum normal), # bound (if bound=9.8813129168249309e-324, the algorithm continues # until the interval cannot be further divided, a larger value # may result in termination before t digits are found). # conditions: f is a continuous function in the interval , b The comma is a punctuation mark that appears in several variants in different languages. Some typefaces render it as a small line, slightly curved or straight, but inclined from the vertical; others give it the appearance of a miniature fille ... # a < b, # and f(a)*f(b) < 0. # output: oot, iterations, convergence, termination condition #############################################################################N if b <= a: return loat("NAN"), 0, "No convergence", "b < a" fa = f(a) fb = f(b) if np.sign(fa) np.sign(fb): return 0"">loat("NAN"), 0, "No convergence", "f(a)*f(b) > 0" en = 0 while en < 2200: en += 1 if np.sign(a) np.sign(b): # avoid overflow c = a + (b - a)/2 else: c = (a + b)/2 fc = f(c) if b - a <= bound: return ound, en, "No convergence", "Bound reached" if fc 0: return , en, "Converged", "f(c) = 0" if b - a <= abs(c) * tol: return , en, "Converged", "Tolerance" if np.sign(fa) np.sign(fc): a = c fa = fc else: b = c return loat("NAN"), en, "No convergence", "Bad function"/pre> The first 2 examples test for incorrect input values: 1 bisect(lambda x: x - 1, 5, 1, 5.000000e-15, 9.8813129168249309e-324) Approx. root = nan No convergence after 0 iterations with termination b < a Final interval nan, nan 2 bisect(lambda x: x - 1, 5, 7, 5.000000e-15, 9.8813129168249309e-324) Approx. root = nan No convergence after 0 iterations with termination f(a)*f(b) > 0 Final interval nan, nan/pre> Large roots: 3 bisect(lambda x: x - 12345678901.23456, 0, 1.23457e+14, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 12345678901.23454 Converged after 62 iterations with termination Tolerance Final interval .2345678901234526e+10, 1.2345678901234552e+10 4 bisect(lambda x: x - 1.23456789012456e+100, 0, 2e+100, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890124561e+100 Converged after 50 iterations with termination Tolerance Final interval .2345678901245599e+100, 1.2345678901245619e+100 The final interval is computed as - w/2, c + w/2where w = . This can give good measure as to the accuracy of the approximation Root near maximum: 5 bisect(lambda x: x - 1.234567890123456e+307, 0, 1e+308, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890123454e+307 Converged after 52 iterations with termination Tolerance Final interval .2345678901234535e+307, 1.2345678901234555e+307 Small roots: 6 bisect(lambda x: x - 1.234567890123456e-05, 0, 1, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890123455e-05 Converged after 65 iterations with termination Tolerance Final interval .2345678901234537e-05, 1.2345678901234564e-05 7 bisect(lambda x: x - 1.234567890123456e-100, 0, 1, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890123454e-100 Converged after 381 iterations with termination Tolerance Final interval .2345678901234532e-100, 1.2345678901234552e-100 Ex. 8 is beyond the minimum normal but gives a fairly good result because the approximation has a small interval. Calculations for values in the subnormal range can produce unexpected results. 8 bisect(lambda x: x - 1.234567890123457e-310, 0, 1, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890123457e-310 Converged after 1071 iterations with termination f(c) = 0 Final interval .2345678901232595e-310, 1.2345678901236548e-310 If the return state is 'f(c) = 0', then the desired tolerance may not have been achieved. This can be checked by lowering the tolerance until a return state of 'Tolerance' is achieved. 8a bisect(lambda x: x - 1.234567890123457e-310, 0, 1, 5.000000e-13) Approx. root = 1.234567890123457e-310 Converged after 1071 iterations with termination f(c) = 0 Final interval .2345678901232595e-310, 1.2345678901236548e-310 8b bisect(lambda x: x - 1.234567890123457e-310, 0, 1, 5.000000e-12) Approx. root = 1.234567890124643e-310 Converged after 1069 iterations with termination Tolerance Final interval .2345678901238524e-310, 1.2345678901254334e-310 8b shows that the result has 12 digits. Even though the root is outside the 'normal' range, it may still be possible to achieve results with good tolerance. 9 bisect(lambda x: x - 1.234567891003685e-315, 0, 1, 5.000000e-03, 9.8813129168249309e-324) Approx. root = 1.23558592808891e-315 Converged after 1055 iterations with termination Tolerance Final interval .2342907646422757e-315, 1.2368810915355439e-3151.2368810915355439e-315] Ex. 10 shows the maximum number of iterations that should be expected: 10 bisect(lambda x: x - 1.234567891003685e-315, -1e+307, 1e+307, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567891003685e-315 Converged after 2093 iterations with termination f(c) = 0 Final interval .2345678910036845e-315, 1.2345678910036845e-315 There may be situations in which a 'good' approximation is not required. This can be achieved by changing the 'Bound': 11 bisect(lambda x: x - 1.234567890123457e-100, 0, 1, 5.000000e-15, 4.9999999999999997e-12) Approx. root = 5e-12 No convergence after 39 iterations with termination Bound reached Final interval .0905052982270715e-12, 5.9094947017729279e-12 Evaluation of the final interval may assist in determining accuracy. The following show the behavior of subnormal numbers And shows how the significant digits are lost: print(1.234567890123456e-310) 1.23456789012346e-310 print(1.234567890123456e-312) 1.234567890124e-312 print(1.234567890123456e-315) 1.23456789e-315 print(1.234567890123456e-317) 1.234568e-317 print(1.234567890123456e-319) 1.23457e-319 print(1.234567890123456e-321) 1.235e-321 print(1.234567890123456e-323) 1e-323 print(1.234567890123456e-324) 0.0 These examples show that this method gives 15 digit accuracy for functions of the form f(x) = (x - r) g(x) for all r in the range of normal numbers. Higher order roots Further problems can arise from the use of computer arithmetic for higher order roots. To help in considering how to detect and correct inaccurate results consider the following: bisect(lambda x: (x - 1.23456789012345e-100), 0, 1, 5e-15) Approx. root = 1.23456789012345e-100 Converged after 381 iterations with termination f(c) = 0 Final interval .2345678901234491e-100, 1.2345678901234511e-100 The final interval .2345678901234491e-100, 1.2345678901234511e-100indicates fairly good accuracy. The bisection method has a distinct advantage over other root finding techniques in that the final interval can be used to determine the accuracy of the final solution. This information will be useful in assessing the accuracy of some following examples. Next consider what happens for a root of order 3: bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-15) Approx. root = 1.234567898094279e-100 Converged after 357 iterations with termination f(c) = 0 Final interval .2345678810624394e-100, 1.2345679151261181e-100 The final interval .2345678810624394e-100, 1.2345679151261181e-100indicates that 15 digits have not been returned. The relative error (1.234567898094279e-100 - 1.23456789012345e-100)/1.23456789012345e-100 = 6.456371473106003e-09 shows that only 8 digits are correct and again f(c) = 0. This occurs because \begin f(approx. root) &= f(1.234567898094279*10^) \\ &= (1.234567898094279*10^ - 1.23456789012345*10^)^3 \\ &= (7.970828885817127*10^)^3 \\ &= 5.064195*10^*10^ \\ &= 5.064195*10^\end Because this is less than the minimum subnormal, it returns a value of 0. This can occur in any root finding technique, not just the bisection method, and it is only the fact that the return conditions include the information about what stopping criteria was achieved that the problem can be diagnosed. The use of the relative error as a stopping condition allows us to determine how accurate a solution can be obtained. Consider what happens on trying to achieve 8 significant figures: bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-8) .2345678980942788e-100, 357, 'Converged', 'f(c) = 0' f(c) = 0 Indicates that eight digits of accuracy have not been achieved, so try bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-4) .2347947281308757e-100, 344, 'Converged', 'Tolerance' At least four digits have been achieved and bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-6) .2345658202098768e-100, 351, 'Converged', 'Tolerance' 6 digit convergence bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-7) .2345677277758852e-100, 354, 'Converged', 'Tolerance' 7 digit convergence A similar problem can arise if there are two small roots close together: bisect(lambda x: (x - 1.23456789012345e-23)*x, 1e-300, 1, 5e-15) .2345678901234481e-23, 125, 'Converged', 'Tolerance' 15 digit convergence bisect(lambda x: (x - 1.23456789012345e-24)*x, 1e-300, 1e-20, 5e-1) .5509016039626554e-300, 931, 'Converged', 'f(c) = 0' Final interval .2754508019813276e-300, 1.8263524059439830e-300relative error = 3.5521376891678086e-1 -- 1 digit convergence bisect(lambda x: (x - 1.23456789012345e-23)*x, 1e-300, 1, 5e-1) .1580528575742387e-23, 79, 'Converged', 'Tolerance' Final interval .0753347963189360e-23, 1.2407709188295415e-23relative error = 1.4285714285714285e-1 -- 1 digit convergence (The following has not been changed.) Generalization to higher dimensions The bisection method has been generalized to multi-dimensional functions. Such methods are called generalized bisection methods. Methods based on degree computation Some of these methods are based on computing the topological degree In mathematics, topological degree theory is a generalization of the winding number of a curve in the complex plane. It can be used to estimate the number of solutions of an equation, and is closely connected to fixed-point theory. When one solutio ..., which for a bounded region \Omega \subseteq \mathbb^n and a differentiable function f: \mathbb^n \rightarrow \mathbb^n is defined as a sum over its roots: :\deg(f, \Omega) := \sum_ \sgn \det(Df(y)), where Df(y) is the Jacobian matrix In vector calculus, the Jacobian matrix (, ) of a vector-valued function of several variables is the matrix of all its first-order partial derivatives. If this matrix is square, that is, if the number of variables equals the number of component ..., \mathbf = (0,0,...,0)^T, and :\sgn(x) = \begin 1, & x>0 \\ 0, & x=0 \\ -1, & x<0 \\ \end is the sign function In mathematics, the sign function or signum function (from '' signum'', Latin for "sign") is a function that has the value , or according to whether the sign of a given real number is positive or negative, or the given number is itself zer .... In order for a root to exist, it is sufficient that \deg(f, \Omega) \neq 0, and this can be verified using a surface integral In mathematics, particularly multivariable calculus, a surface integral is a generalization of multiple integrals to integration over surfaces. It can be thought of as the double integral analogue of the line integral. Given a surface, o ... over the boundary of \Omega. Characteristic bisection method The characteristic bisection method uses only the signs of a function in different points. Lef ''f'' be a function from Rd to Rd, for some integer ''d'' ≥ 2. A characteristic polyhedron (also called an admissible polygon) of ''f'' is a polytope In elementary geometry, a polytope is a geometric object with flat sides ('' faces''). Polytopes are the generalization of three-dimensional polyhedra to any number of dimensions. Polytopes may exist in any general number of dimensions as an ... in R''d'', having 2d vertices, such that in each vertex v, the combination of signs of ''f''(v) is unique and the topological degree of ''f'' on its interior is not zero (a necessary criterion to ensure the existence of a root). For example, for ''d''=2, a characteristic polyhedron of ''f'' is a quadrilateral In Euclidean geometry, geometry a quadrilateral is a four-sided polygon, having four Edge (geometry), edges (sides) and four Vertex (geometry), corners (vertices). The word is derived from the Latin words ''quadri'', a variant of four, and ''l ... with vertices (say) A,B,C,D, such that: * , that is, ''f''1(A)<0, ''f''2(A)<0. * , that is, ''f''1(B)<0, ''f''2(B)>0. * , that is, ''f''1(C)>0, ''f''2(C)<0. * , that is, ''f''1(D)>0, ''f''2(D)>0. A proper edge of a characteristic polygon is a edge between a pair of vertices, such that the sign vector differs by only a single sign. In the above example, the proper edges of the characteristic quadrilateral are AB, AC, BD and CD. A diagonal is a pair of vertices, such that the sign vector differs by all ''d'' signs. In the above example, the diagonals are AD and BC. At each iteration, the algorithm picks a proper edge of the polyhedron (say, AB), and computes the signs of ''f'' in its mid-point (say, M). Then it proceeds as follows: * If , then A is replaced by M, and we get a smaller characteristic polyhedron. * If , then B is replaced by M, and we get a smaller characteristic polyhedron. * Else, we pick a new proper edge and try again. Suppose the diameter (= length of longest proper edge) of the original characteristic polyhedron is . Then, at least \log_2(D/\varepsilon) bisections of edges are required so that the diameter of the remaining polygon will be at most . If the topological degree of the initial polyhedron is not zero, then there is a procedure that can choose an edge such that the next polyhedron also has nonzero degree. See also *Binary search algorithm In computer science, binary search, also known as half-interval search, logarithmic search, or binary chop, is a search algorithm that finds the position of a target value within a sorted array. Binary search compares the target value to the ... *Lehmer–Schur algorithm In mathematics, the Lehmer–Schur algorithm (named after Derrick Henry Lehmer and Issai Schur) is a root-finding algorithm for complex polynomials, extending the idea of enclosing roots like in the one-dimensional bisection method to the complex ..., generalization of the bisection method in the complex plane *Nested intervals In mathematics, a sequence of nested intervals can be intuitively understood as an ordered collection of Interval (mathematics), intervals I_n on the Interval (mathematics), real number line with natural number, natural numbers n=1,2,3,\dots as a ... References * Further reading * * External links * Bisection MethodNotes, PPT, Mathcad, Maple, Matlab, Mathematica froHolistic Numerical Methods Institute{{Root-finding algorithms Articles with example pseudocode Root-finding algorithms
1 bisect(lambda x: x - 1, 5, 1, 5.000000e-15, 9.8813129168249309e-324) Approx. root = nan No convergence after 0 iterations with termination b < a Final interval nan, nan 2 bisect(lambda x: x - 1, 5, 7, 5.000000e-15, 9.8813129168249309e-324) Approx. root = nan No convergence after 0 iterations with termination f(a)*f(b) > 0 Final interval nan, nan/pre> Large roots: 3 bisect(lambda x: x - 12345678901.23456, 0, 1.23457e+14, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 12345678901.23454 Converged after 62 iterations with termination Tolerance Final interval .2345678901234526e+10, 1.2345678901234552e+10 4 bisect(lambda x: x - 1.23456789012456e+100, 0, 2e+100, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890124561e+100 Converged after 50 iterations with termination Tolerance Final interval .2345678901245599e+100, 1.2345678901245619e+100 The final interval is computed as - w/2, c + w/2where w = . This can give good measure as to the accuracy of the approximation Root near maximum: 5 bisect(lambda x: x - 1.234567890123456e+307, 0, 1e+308, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890123454e+307 Converged after 52 iterations with termination Tolerance Final interval .2345678901234535e+307, 1.2345678901234555e+307 Small roots: 6 bisect(lambda x: x - 1.234567890123456e-05, 0, 1, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890123455e-05 Converged after 65 iterations with termination Tolerance Final interval .2345678901234537e-05, 1.2345678901234564e-05 7 bisect(lambda x: x - 1.234567890123456e-100, 0, 1, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890123454e-100 Converged after 381 iterations with termination Tolerance Final interval .2345678901234532e-100, 1.2345678901234552e-100 Ex. 8 is beyond the minimum normal but gives a fairly good result because the approximation has a small interval. Calculations for values in the subnormal range can produce unexpected results. 8 bisect(lambda x: x - 1.234567890123457e-310, 0, 1, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890123457e-310 Converged after 1071 iterations with termination f(c) = 0 Final interval .2345678901232595e-310, 1.2345678901236548e-310 If the return state is 'f(c) = 0', then the desired tolerance may not have been achieved. This can be checked by lowering the tolerance until a return state of 'Tolerance' is achieved. 8a bisect(lambda x: x - 1.234567890123457e-310, 0, 1, 5.000000e-13) Approx. root = 1.234567890123457e-310 Converged after 1071 iterations with termination f(c) = 0 Final interval .2345678901232595e-310, 1.2345678901236548e-310 8b bisect(lambda x: x - 1.234567890123457e-310, 0, 1, 5.000000e-12) Approx. root = 1.234567890124643e-310 Converged after 1069 iterations with termination Tolerance Final interval .2345678901238524e-310, 1.2345678901254334e-310 8b shows that the result has 12 digits. Even though the root is outside the 'normal' range, it may still be possible to achieve results with good tolerance. 9 bisect(lambda x: x - 1.234567891003685e-315, 0, 1, 5.000000e-03, 9.8813129168249309e-324) Approx. root = 1.23558592808891e-315 Converged after 1055 iterations with termination Tolerance Final interval .2342907646422757e-315, 1.2368810915355439e-3151.2368810915355439e-315] Ex. 10 shows the maximum number of iterations that should be expected: 10 bisect(lambda x: x - 1.234567891003685e-315, -1e+307, 1e+307, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567891003685e-315 Converged after 2093 iterations with termination f(c) = 0 Final interval .2345678910036845e-315, 1.2345678910036845e-315 There may be situations in which a 'good' approximation is not required. This can be achieved by changing the 'Bound': 11 bisect(lambda x: x - 1.234567890123457e-100, 0, 1, 5.000000e-15, 4.9999999999999997e-12) Approx. root = 5e-12 No convergence after 39 iterations with termination Bound reached Final interval .0905052982270715e-12, 5.9094947017729279e-12 Evaluation of the final interval may assist in determining accuracy. The following show the behavior of subnormal numbers And shows how the significant digits are lost: print(1.234567890123456e-310) 1.23456789012346e-310 print(1.234567890123456e-312) 1.234567890124e-312 print(1.234567890123456e-315) 1.23456789e-315 print(1.234567890123456e-317) 1.234568e-317 print(1.234567890123456e-319) 1.23457e-319 print(1.234567890123456e-321) 1.235e-321 print(1.234567890123456e-323) 1e-323 print(1.234567890123456e-324) 0.0 These examples show that this method gives 15 digit accuracy for functions of the form f(x) = (x - r) g(x) for all r in the range of normal numbers. Higher order roots Further problems can arise from the use of computer arithmetic for higher order roots. To help in considering how to detect and correct inaccurate results consider the following: bisect(lambda x: (x - 1.23456789012345e-100), 0, 1, 5e-15) Approx. root = 1.23456789012345e-100 Converged after 381 iterations with termination f(c) = 0 Final interval .2345678901234491e-100, 1.2345678901234511e-100 The final interval .2345678901234491e-100, 1.2345678901234511e-100indicates fairly good accuracy. The bisection method has a distinct advantage over other root finding techniques in that the final interval can be used to determine the accuracy of the final solution. This information will be useful in assessing the accuracy of some following examples. Next consider what happens for a root of order 3: bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-15) Approx. root = 1.234567898094279e-100 Converged after 357 iterations with termination f(c) = 0 Final interval .2345678810624394e-100, 1.2345679151261181e-100 The final interval .2345678810624394e-100, 1.2345679151261181e-100indicates that 15 digits have not been returned. The relative error (1.234567898094279e-100 - 1.23456789012345e-100)/1.23456789012345e-100 = 6.456371473106003e-09 shows that only 8 digits are correct and again f(c) = 0. This occurs because \begin f(approx. root) &= f(1.234567898094279*10^) \\ &= (1.234567898094279*10^ - 1.23456789012345*10^)^3 \\ &= (7.970828885817127*10^)^3 \\ &= 5.064195*10^*10^ \\ &= 5.064195*10^\end Because this is less than the minimum subnormal, it returns a value of 0. This can occur in any root finding technique, not just the bisection method, and it is only the fact that the return conditions include the information about what stopping criteria was achieved that the problem can be diagnosed. The use of the relative error as a stopping condition allows us to determine how accurate a solution can be obtained. Consider what happens on trying to achieve 8 significant figures: bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-8) .2345678980942788e-100, 357, 'Converged', 'f(c) = 0' f(c) = 0 Indicates that eight digits of accuracy have not been achieved, so try bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-4) .2347947281308757e-100, 344, 'Converged', 'Tolerance' At least four digits have been achieved and bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-6) .2345658202098768e-100, 351, 'Converged', 'Tolerance' 6 digit convergence bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-7) .2345677277758852e-100, 354, 'Converged', 'Tolerance' 7 digit convergence A similar problem can arise if there are two small roots close together: bisect(lambda x: (x - 1.23456789012345e-23)*x, 1e-300, 1, 5e-15) .2345678901234481e-23, 125, 'Converged', 'Tolerance' 15 digit convergence bisect(lambda x: (x - 1.23456789012345e-24)*x, 1e-300, 1e-20, 5e-1) .5509016039626554e-300, 931, 'Converged', 'f(c) = 0' Final interval .2754508019813276e-300, 1.8263524059439830e-300relative error = 3.5521376891678086e-1 -- 1 digit convergence bisect(lambda x: (x - 1.23456789012345e-23)*x, 1e-300, 1, 5e-1) .1580528575742387e-23, 79, 'Converged', 'Tolerance' Final interval .0753347963189360e-23, 1.2407709188295415e-23relative error = 1.4285714285714285e-1 -- 1 digit convergence (The following has not been changed.) Generalization to higher dimensions The bisection method has been generalized to multi-dimensional functions. Such methods are called generalized bisection methods. Methods based on degree computation Some of these methods are based on computing the topological degree In mathematics, topological degree theory is a generalization of the winding number of a curve in the complex plane. It can be used to estimate the number of solutions of an equation, and is closely connected to fixed-point theory. When one solutio ..., which for a bounded region \Omega \subseteq \mathbb^n and a differentiable function f: \mathbb^n \rightarrow \mathbb^n is defined as a sum over its roots: :\deg(f, \Omega) := \sum_ \sgn \det(Df(y)), where Df(y) is the Jacobian matrix In vector calculus, the Jacobian matrix (, ) of a vector-valued function of several variables is the matrix of all its first-order partial derivatives. If this matrix is square, that is, if the number of variables equals the number of component ..., \mathbf = (0,0,...,0)^T, and :\sgn(x) = \begin 1, & x>0 \\ 0, & x=0 \\ -1, & x<0 \\ \end is the sign function In mathematics, the sign function or signum function (from '' signum'', Latin for "sign") is a function that has the value , or according to whether the sign of a given real number is positive or negative, or the given number is itself zer .... In order for a root to exist, it is sufficient that \deg(f, \Omega) \neq 0, and this can be verified using a surface integral In mathematics, particularly multivariable calculus, a surface integral is a generalization of multiple integrals to integration over surfaces. It can be thought of as the double integral analogue of the line integral. Given a surface, o ... over the boundary of \Omega. Characteristic bisection method The characteristic bisection method uses only the signs of a function in different points. Lef ''f'' be a function from Rd to Rd, for some integer ''d'' ≥ 2. A characteristic polyhedron (also called an admissible polygon) of ''f'' is a polytope In elementary geometry, a polytope is a geometric object with flat sides ('' faces''). Polytopes are the generalization of three-dimensional polyhedra to any number of dimensions. Polytopes may exist in any general number of dimensions as an ... in R''d'', having 2d vertices, such that in each vertex v, the combination of signs of ''f''(v) is unique and the topological degree of ''f'' on its interior is not zero (a necessary criterion to ensure the existence of a root). For example, for ''d''=2, a characteristic polyhedron of ''f'' is a quadrilateral In Euclidean geometry, geometry a quadrilateral is a four-sided polygon, having four Edge (geometry), edges (sides) and four Vertex (geometry), corners (vertices). The word is derived from the Latin words ''quadri'', a variant of four, and ''l ... with vertices (say) A,B,C,D, such that: * , that is, ''f''1(A)<0, ''f''2(A)<0. * , that is, ''f''1(B)<0, ''f''2(B)>0. * , that is, ''f''1(C)>0, ''f''2(C)<0. * , that is, ''f''1(D)>0, ''f''2(D)>0. A proper edge of a characteristic polygon is a edge between a pair of vertices, such that the sign vector differs by only a single sign. In the above example, the proper edges of the characteristic quadrilateral are AB, AC, BD and CD. A diagonal is a pair of vertices, such that the sign vector differs by all ''d'' signs. In the above example, the diagonals are AD and BC. At each iteration, the algorithm picks a proper edge of the polyhedron (say, AB), and computes the signs of ''f'' in its mid-point (say, M). Then it proceeds as follows: * If , then A is replaced by M, and we get a smaller characteristic polyhedron. * If , then B is replaced by M, and we get a smaller characteristic polyhedron. * Else, we pick a new proper edge and try again. Suppose the diameter (= length of longest proper edge) of the original characteristic polyhedron is . Then, at least \log_2(D/\varepsilon) bisections of edges are required so that the diameter of the remaining polygon will be at most . If the topological degree of the initial polyhedron is not zero, then there is a procedure that can choose an edge such that the next polyhedron also has nonzero degree. See also *Binary search algorithm In computer science, binary search, also known as half-interval search, logarithmic search, or binary chop, is a search algorithm that finds the position of a target value within a sorted array. Binary search compares the target value to the ... *Lehmer–Schur algorithm In mathematics, the Lehmer–Schur algorithm (named after Derrick Henry Lehmer and Issai Schur) is a root-finding algorithm for complex polynomials, extending the idea of enclosing roots like in the one-dimensional bisection method to the complex ..., generalization of the bisection method in the complex plane *Nested intervals In mathematics, a sequence of nested intervals can be intuitively understood as an ordered collection of Interval (mathematics), intervals I_n on the Interval (mathematics), real number line with natural number, natural numbers n=1,2,3,\dots as a ... References * Further reading * * External links * Bisection MethodNotes, PPT, Mathcad, Maple, Matlab, Mathematica froHolistic Numerical Methods Institute{{Root-finding algorithms Articles with example pseudocode Root-finding algorithms
3 bisect(lambda x: x - 12345678901.23456, 0, 1.23457e+14, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 12345678901.23454 Converged after 62 iterations with termination Tolerance Final interval .2345678901234526e+10, 1.2345678901234552e+10 4 bisect(lambda x: x - 1.23456789012456e+100, 0, 2e+100, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890124561e+100 Converged after 50 iterations with termination Tolerance Final interval .2345678901245599e+100, 1.2345678901245619e+100
5 bisect(lambda x: x - 1.234567890123456e+307, 0, 1e+308, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890123454e+307 Converged after 52 iterations with termination Tolerance Final interval .2345678901234535e+307, 1.2345678901234555e+307
6 bisect(lambda x: x - 1.234567890123456e-05, 0, 1, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890123455e-05 Converged after 65 iterations with termination Tolerance Final interval .2345678901234537e-05, 1.2345678901234564e-05 7 bisect(lambda x: x - 1.234567890123456e-100, 0, 1, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890123454e-100 Converged after 381 iterations with termination Tolerance Final interval .2345678901234532e-100, 1.2345678901234552e-100
8 bisect(lambda x: x - 1.234567890123457e-310, 0, 1, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567890123457e-310 Converged after 1071 iterations with termination f(c) = 0 Final interval .2345678901232595e-310, 1.2345678901236548e-310
8a bisect(lambda x: x - 1.234567890123457e-310, 0, 1, 5.000000e-13) Approx. root = 1.234567890123457e-310 Converged after 1071 iterations with termination f(c) = 0 Final interval .2345678901232595e-310, 1.2345678901236548e-310 8b bisect(lambda x: x - 1.234567890123457e-310, 0, 1, 5.000000e-12) Approx. root = 1.234567890124643e-310 Converged after 1069 iterations with termination Tolerance Final interval .2345678901238524e-310, 1.2345678901254334e-310
9 bisect(lambda x: x - 1.234567891003685e-315, 0, 1, 5.000000e-03, 9.8813129168249309e-324) Approx. root = 1.23558592808891e-315 Converged after 1055 iterations with termination Tolerance Final interval .2342907646422757e-315, 1.2368810915355439e-3151.2368810915355439e-315]
10 bisect(lambda x: x - 1.234567891003685e-315, -1e+307, 1e+307, 5.000000e-15, 9.8813129168249309e-324) Approx. root = 1.234567891003685e-315 Converged after 2093 iterations with termination f(c) = 0 Final interval .2345678910036845e-315, 1.2345678910036845e-315
11 bisect(lambda x: x - 1.234567890123457e-100, 0, 1, 5.000000e-15, 4.9999999999999997e-12) Approx. root = 5e-12 No convergence after 39 iterations with termination Bound reached Final interval .0905052982270715e-12, 5.9094947017729279e-12
print(1.234567890123456e-310) 1.23456789012346e-310 print(1.234567890123456e-312) 1.234567890124e-312 print(1.234567890123456e-315) 1.23456789e-315 print(1.234567890123456e-317) 1.234568e-317 print(1.234567890123456e-319) 1.23457e-319 print(1.234567890123456e-321) 1.235e-321 print(1.234567890123456e-323) 1e-323 print(1.234567890123456e-324) 0.0
Higher order roots
bisect(lambda x: (x - 1.23456789012345e-100), 0, 1, 5e-15) Approx. root = 1.23456789012345e-100 Converged after 381 iterations with termination f(c) = 0 Final interval .2345678901234491e-100, 1.2345678901234511e-100
bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-15) Approx. root = 1.234567898094279e-100 Converged after 357 iterations with termination f(c) = 0 Final interval .2345678810624394e-100, 1.2345679151261181e-100
(1.234567898094279e-100 - 1.23456789012345e-100)/1.23456789012345e-100 = 6.456371473106003e-09
bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-8) .2345678980942788e-100, 357, 'Converged', 'f(c) = 0'
bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-4) .2347947281308757e-100, 344, 'Converged', 'Tolerance'
bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-6) .2345658202098768e-100, 351, 'Converged', 'Tolerance' 6 digit convergence
bisect(lambda x: (x - 1.23456789012345e-100)**3, 0, 1, 5e-7) .2345677277758852e-100, 354, 'Converged', 'Tolerance' 7 digit convergence
bisect(lambda x: (x - 1.23456789012345e-23)*x, 1e-300, 1, 5e-15) .2345678901234481e-23, 125, 'Converged', 'Tolerance'
bisect(lambda x: (x - 1.23456789012345e-24)*x, 1e-300, 1e-20, 5e-1) .5509016039626554e-300, 931, 'Converged', 'f(c) = 0' Final interval .2754508019813276e-300, 1.8263524059439830e-300relative error = 3.5521376891678086e-1 -- 1 digit convergence
bisect(lambda x: (x - 1.23456789012345e-23)*x, 1e-300, 1, 5e-1) .1580528575742387e-23, 79, 'Converged', 'Tolerance' Final interval .0753347963189360e-23, 1.2407709188295415e-23relative error = 1.4285714285714285e-1 -- 1 digit convergence
Generalization to higher dimensions
Methods based on degree computation
Characteristic bisection method
See also
References
Further reading
External links