%{ Roots (both single and multiple) of an equation f(x)=0 using five methods Methods: Bisectional, False position, Secant, Brute force also using Matlab function fzero February 2022 by AG. %} clear % Clears command window clc % Clears command history clearvars % Clear variables from memory clf('reset')% Removes anything in the figure window before simulation. tic % set timer for the program % Initial data ============================== a = -10.0; % left-end point b = 2.0; % right-end point x0= 1.0; % guess point for Secant and Matlab (root) eps = 1.0e-8; % desired uncertainity of the root Nint= 100; % number of subintervals for brute force method % Name of the integrand @f f0=@f; %============================================ % Estimate number of steps for given tolerance Nsteps = ceil((1.0/log(2))*log((b-a)/eps)); format1 = ' %3i %10.6f %10.6f '; format2 = ' %10.6f %10.6f '; format3 = ' %3i %10.6f %10.6f \n'; fprintf(' Root(s) of f(x) \n') fprintf(' Interval [%4.1f,%4.1f] \n',a,b) fprintf(' Guess Secant and Matlab x0 =%4.1f \n',x0) fprintf(' Tolerance = %6.2e \n',eps) % fprintf(' Steps for bisectional method %3i \n',Nsteps) fprintf(' iter root f(root)\n') % Step 0: plot the function xf = a: 0.01: b; yf = f(xf); yzero = 0.0*xf; plot(xf,yf,xf,yzero,'LineWidth',1.5) xlabel('x'); ylabel('f(x)'); grid; % 1: Bisectional method [root1,flag] = root_bs(f0, a, b, eps); if flag ~= 0 fprintf(format1,flag, root1,f0(root1)) fprintf(' Bisectional \n') else fprintf(' Bisectional: No root found \n') end % 2: False position method [root2,flag] = root_fp(f0, a, b, eps); if flag ~= 0 fprintf(format1,flag, root2,f0(root2)) fprintf(' False position \n') else fprintf(' False position: No root found \n') end % 3: method of secants x1 = x0; x2 = x1+0.1; [root3,flag] = root_sm(f0, a, b, x0, eps); if flag ~= 0 fprintf(format1,flag, root3,f0(root3)) fprintf(' Secant \n') else fprintf('Secant method - No root found \n') end % 4: Matlab function fzero root4 = fzero(f0,x0); fprintf(format2, root4,f0(root4)) fprintf(' MatLab \n') % 5: Broot force method [Broots, nroots] = Bforce(f0, a, b, eps, Nint); fprintf(' \n Brute force roots\n ') %print solutions if(nroots == 0) fprintf (' No roots found \n') return else fprintf(' n root f(root)\n') for i=1:nroots fprintf(format3,i, Broots(i), f0(Broots(i))) end end fprintf('\n') toc timeE = ceil(toc); %fprintf('\n Elapsed time = %4i sec \n',timeE) %============================== function f=f(x) % use [-10,+10] %f = x + cos(x); % use [-2,2], x0=1 %f = x-cos(x); % easy root at 0.739 % use [-2,2] x0=1 %f = x.^3 - 2*x.^2 + 1.5*x - 1/3; % false position fails (too slow) % use [-2,2] x0=1 %f = 4*x.^4 -6*x.^2 -11/4; % use [-2,2] x0=1 %f = exp(x) - 2.*sin(x) - 2; % very fancy % use [-10,2] f = exp(x).*log(x.^2) - x.*cos(x); %f = exp(x) - x.*sin(x*pi/2.0); end %============================== function [zero,flag] = root_bs(f, a, b, eps) %{ !============================================================ ! Solutions of equation f(x)=0 on [x1,x2] interval ! Method: Bisectional (closed domain) (a single root) !------------------------------------------------------------ ! input ... ! f - function - evaluates f(x) for any x in [x1,x2] ! a - left endpoint of initial interval ! b - right endpoint of initial interval ! eps - desired uncertainity of the root as |b-a|0 - a single root found, flag=number of iterations ! 0 - no solutions for the bisectional method ! <0 - not a root but singularity, flag=number of iterations ! ! Comments: Function f(x) has to change sign between x1 and x2 ! Max number of iterations - 999 (accuracy (b-a)/2*999 %} iter = 999; % Max number of iterations flag = 0; % set success to 0; zero = 99.99; % if there is no root % check the bisection condition if f(a)*f(b) > 0.0 return end % finding a single root xl = a; xr = b; while abs(xr - xl) > eps flag = flag + 1; x0 = (xr + xl)/2.0; if (f(xl) * f(x0)) <= 0.0 xr = x0; else xl = x0; end if(flag >= iter) break end end zero = x0; end % end of root_bs function [zero,flag] = root_fp(f, a, b, eps) %{ !============================================================ ! Solutions of equation f(x)=0 on [x1,x2] interval ! Method: False position (closed domain) (a single root) !------------------------------------------------------------ The same description as root_bs %} iter = 999; % Max number of iterations flag = 0; % initial values for iterations zero = 99.99; % if there is no root % check the bisection condition if f(a)*f(b) > 0.0 return end % finding a single root xl = a; xr = b; x0 = (xr + xl)/2.0; while abs(f(x0)) > eps flag = flag + 1; x0 = xr - (f(xr)*(xr - xl))/(f(xr)-f(xl)); if (f(xl) * f(x0)) <= 0.0 xr = x0; else xl = x0; end if(flag >= iter) break end end zero = x0; end function [zero,flag] = root_sm(f, x1, x2, x0, eps) %{ !============================================================ ! Solutions of equation f(x)=0 on [x1,x2] interval ! Method: Secant method (a single root) !------------------------------------------------------------ ! input ... ! f - function - evaluates f(x) for any x in [x1,x2] ! x1 - initial point ! x2 - second initial point ! eps - desired uncertainity of the root as |b-a|0 - a single root found, flag=number of iterations ! 0 - no solutions for the bisectional method ! <0 - not a root but singularity, flag=number of iterations ! ! Comments: Function f(x) has to change sign between x1 and x2 ! Max number of iterations - 999 (accuracy (b-a)/(2*999) %} iter = 999; flag = 0; while (abs(x2 - x1)) > eps flag = flag + 1; if flag == 1 x3 = x0; else x3 = x2 - (f(x2)*(x2-x1))/(f(x2)-f(x1)); end x1 = x2; x2 = x3; if(flag >= iter) break end %end if flag = flag; if (flag == iter) flag = 0; end %end if end % end while zero = x3; end % Brute force method function [Broots, nroots] = Bforce(f, x1, x2, eps, n) Broots(1)=0.0; iter = 200; % initialization dx = (x2-x1)/n; nroots = 0; % loop over subintervals for j=1:n a = x1 + (j-1)*dx; b = a + dx; % check the closed domain condition f(a)*f(b)<0 if(f(a)*f(b)>0) continue end % Iterative refining the solution for i=1:iter c=(b+a)/2.0; if(f(a)*f(c) <= 0.0) b = c; else a=c; end % condition(s) to stop iterations) if(abs(b-a)<= eps) break end end % check if it is a root or singularity root = (b+a)/2.0; if (abs(f(root)) < 1.0) nroots = nroots+1; Broots(nroots)=root; end end end