Càlcul dels zeros d'una funció:

En aquesta pràctica veurem com es poden calcular numèricament els zeros d'una funció.

Teorema de Bolzano: Canvis de signe

Donada una funció f(x), per calcular els seus zeros haurem de fer:
% funció f(x) definida com a inline
f=@(x) sin(x);
%rang de valors que estudiem
xmin=-5;
xmax=5;
pas=0.15;
x=xmin:pas:xmax;
%valors de la funció
y=f(x);
%-------------------------------------------------------------
% pintem la funció per tenir una idea dels zeros
%-------------------------------------------------------------
semieix_y=1.1*max(abs(y)); %ajustem els eixos als valors de la funció
plot(x,y,'.-');
hold on;
axis=[xmin xmax -semieix_y semieix_y];
grid
line([xmin xmax],[0 0],'Color','k','LineWidth',2)
line([0 0],[-semieix_y semieix_y],'Color','k','LineWidth',2)

Determinació de l'interval de canvi de signe

%-------------------------------------------------------------
% Determinem els possibles zeros de la funció.
%-------------------------------------------------------------
%
% Fem un estudi del numero de zeros a partir dels canvis de signe de la
% funció
nzeros=0;
intervals=[];
for j=1:length(y)-1
if ( y(j)*y(j+1) <= 0 )
nzeros=nzeros+1;
plot(x(j),y(j),'ro')
plot(x(j+1),y(j+1),'yd')
disp(['zero ', num2str(nzeros)]);
disp(['interval [' num2str(x(j)) ',' num2str(x(j+1)) ']']);
intervals=[intervals; x(j), x(j+1)]; %guardem els intervals en una matriu
end
end
zero 1
interval [-3.2,-3.05]
zero 2
interval [-0.05,0.1]
zero 3
interval [3.1,3.25]

Mètode de la Bisecció

Es basa en dividir succesivament la meitat l'interval inicial [a,b], en el que hi ha un canvi de signe i anar descartant la meitat que ja no conté el canvi de signe (trobareu el codi al final del guió).
Iteracions de la bisecció

Càlcul del zero a cada interval

Ara per cada interval cridarem una funció que calculi el zero fins a una determinada tolerància d'error . Aquest criteri és suficient si la funció és prou vertical però en general és més precís utilitzar que que sempre donarà un valor més proper al zero real.
tol=1.e-8; % demanem 10^(-8) de precisió en el càlcul
numZeros = size(intervals,1); %cada fila és un interval [xa, xb] de canvi de signe
for i=1:numZeros
xa=intervals(i,1);
xb=intervals(i,2);
z(i)=biseccio(f, xa, xb, tol); %s'ha de triar el mètode a utilitzar
%z(i)=secant(f, xa, xb, tol);
end
iter = 1 x= -3.1250000000000000e+00 f(x)= -1.659189e-02 iter = 2 x= -3.1625000000000001e+00 f(x)= 2.090582e-02 iter = 3 x= -3.1437499999999998e+00 f(x)= 2.157345e-03 iter = 4 x= -3.1343749999999999e+00 f(x)= -7.217591e-03 iter = 5 x= -3.1390624999999996e+00 f(x)= -2.530151e-03 iter = 6 x= -3.1414062499999997e+00 f(x)= -1.864036e-04 iter = 7 x= -3.1425781250000000e+00 f(x)= 9.854713e-04 iter = 8 x= -3.1419921874999996e+00 f(x)= 3.995339e-04 iter = 9 x= -3.1416992187499995e+00 f(x)= 1.065652e-04 iter = 10 x= -3.1415527343749998e+00 f(x)= -3.991921e-05 iter = 11 x= -3.1416259765624996e+00 f(x)= 3.332297e-05 iter = 12 x= -3.1415893554687497e+00 f(x)= -3.298121e-06 iter = 13 x= -3.1416076660156245e+00 f(x)= 1.501243e-05 iter = 14 x= -3.1415985107421873e+00 f(x)= 5.857152e-06 iter = 15 x= -3.1415939331054688e+00 f(x)= 1.279516e-06 iter = 16 x= -3.1415916442871090e+00 f(x)= -1.009303e-06 iter = 17 x= -3.1415927886962889e+00 f(x)= 1.351065e-07 iter = 18 x= -3.1415922164916990e+00 f(x)= -4.370981e-07 iter = 19 x= -3.1415925025939941e+00 f(x)= -1.509958e-07 iter = 20 x= -3.1415926456451415e+00 f(x)= -7.944652e-09 -------------------------------- iter = 1 x= 2.5000000000000355e-02 f(x)= 2.499740e-02 iter = 2 x= -1.2499999999999734e-02 f(x)= -1.249967e-02 iter = 3 x= 6.2500000000003109e-03 f(x)= 6.249959e-03 iter = 4 x= -3.1249999999997113e-03 f(x)= -3.124995e-03 iter = 5 x= 1.5625000000002998e-03 f(x)= 1.562499e-03 iter = 6 x= -7.8124999999970579e-04 f(x)= -7.812499e-04 iter = 7 x= 3.9062500000029698e-04 f(x)= 3.906250e-04 iter = 8 x= -1.9531249999970440e-04 f(x)= -1.953125e-04 iter = 9 x= 9.7656250000296291e-05 f(x)= 9.765625e-05 iter = 10 x= -4.8828124999704056e-05 f(x)= -4.882812e-05 iter = 11 x= 2.4414062500296117e-05 f(x)= 2.441406e-05 iter = 12 x= -1.2207031249703969e-05 f(x)= -1.220703e-05 iter = 13 x= 6.1035156252960739e-06 f(x)= 6.103516e-06 iter = 14 x= -3.0517578122039478e-06 f(x)= -3.051758e-06 iter = 15 x= 1.5258789065460631e-06 f(x)= 1.525879e-06 iter = 16 x= -7.6293945282894233e-07 f(x)= -7.629395e-07 iter = 17 x= 3.8146972685856038e-07 f(x)= 3.814697e-07 iter = 18 x= -1.9073486298519098e-07 f(x)= -1.907349e-07 iter = 19 x= 9.5367431936684699e-08 f(x)= 9.536743e-08 iter = 20 x= -4.7683715524253140e-08 f(x)= -4.768372e-08 iter = 21 x= 2.3841858206215780e-08 f(x)= 2.384186e-08 iter = 22 x= -1.1920928659018680e-08 f(x)= -1.192093e-08 iter = 23 x= 5.9604647735985499e-09 f(x)= 5.960465e-09 -------------------------------- iter = 1 x= 3.1750000000000007e+00 f(x)= -3.340113e-02 iter = 2 x= 3.1375000000000006e+00 f(x)= 4.092642e-03 iter = 3 x= 3.1562500000000009e+00 f(x)= -1.465682e-02 iter = 4 x= 3.1468750000000005e+00 f(x)= -5.282322e-03 iter = 5 x= 3.1421875000000004e+00 f(x)= -5.948464e-04 iter = 6 x= 3.1398437500000007e+00 f(x)= 1.748903e-03 iter = 7 x= 3.1410156250000005e+00 f(x)= 5.770286e-04 iter = 8 x= 3.1416015625000004e+00 f(x)= -8.908910e-06 iter = 9 x= 3.1413085937500007e+00 f(x)= 2.840598e-04 iter = 10 x= 3.1414550781250004e+00 f(x)= 1.375755e-04 iter = 11 x= 3.1415283203125002e+00 f(x)= 6.433328e-05 iter = 12 x= 3.1415649414062505e+00 f(x)= 2.771218e-05 iter = 13 x= 3.1415832519531257e+00 f(x)= 9.401637e-06 iter = 14 x= 3.1415924072265629e+00 f(x)= 2.463632e-07 iter = 15 x= 3.1415969848632814e+00 f(x)= -4.331273e-06 iter = 16 x= 3.1415946960449221e+00 f(x)= -2.042455e-06 iter = 17 x= 3.1415935516357427e+00 f(x)= -8.980459e-07 iter = 18 x= 3.1415929794311528e+00 f(x)= -3.258414e-07 iter = 19 x= 3.1415926933288576e+00 f(x)= -3.973906e-08 iter = 20 x= 3.1415925502777102e+00 f(x)= 1.033121e-07 iter = 21 x= 3.1415926218032837e+00 f(x)= 3.178651e-08 iter = 22 x= 3.1415926575660706e+00 f(x)= -3.976277e-09 --------------------------------
disp('zeros :');
zeros :
z
z = 1×41
-3.1416 0.0000 3.1416 -8.1071 -7.4388 -7.1033 -4.9655 -4.2972 -3.9617 -1.8239 -1.1556 -0.8201 1.3177 1.9860 2.3215 4.4593 5.1276 5.4631 7.6009 8.2692 8.6047 10.7425 11.4108 11.7463 3.5343 4.4506 5.1051 5.4978 6.5450 6.6759 7.5922 8.2467 8.6394 9.6866 9.8175 10.7338 11.3883 11.7810 11.3519 11.8446 12.6939

Exercici 1:

Canvieu el criteri de detecció del zero de bisecció per la condició .
Hint: En aquest cas només cal fer i només calen un parell més d'iteracions.
Agafeu la funció en que és una funció molt plana (tota ella està per sota de ) i mireu la diferència entre els dos criteris (el segon sempre és més precís!!)

Exercici 2: Mètode de la secant (regula fals)

Implementeu el mètode de la secant creant una funció de Matlab
function zero = secant(f, xa, xb, tol)
i substituiu en el programa anterior la crida a biseccio per la crida a secant.
Mètode de la secant:
Anàlogament al que es fa en el mètode de bisecció, es pot fer el mateix però triant com a punt intermedi c, el punt de tall de l'eix x (y=0) amb la recta que uneix els dos punts (a,f(a)) i (b,fb)).
Podeu comprovar que la fórmula és:
A partir d'aquí es procedeix exactament igual que a bisecció, es descarta el subinterval que no conté el zero.
(source https://planetcalc.com/3712/)
Solució: Pel primer dels zeros només calen dues iteracions i donen:
iter = 1 x= -3.1415994094031583e+00 f(x)= 6.755813e-06
iter = 2 x= -3.1415926532799121e+00 f(x)= -3.098811e-10

Exercici 2: Calcul dels zeros d'una funció

Calculeu els zeros de la funció
dins l'interval [-5,-1.5], pas entre les x de 0.02 i amb una tol = 1.e-10
Solució: Hi ha un total de 7 zeros
-4.7949e+00 -4.4553e+00 -4.0875e+00 -3.6833e+00 -3.2287e+00 -2.6987e+00 -2.0351e+00

Exercicis:(by P. Gutiérrez)

(1) Representeu, a l'interval la gràfica de la funció (en color vermell), i la gràfica del seu polinomi de Taylor de grau 3 a l'origen, (en línia discontínua de color negre), totes dues a la mateixa finestra.
%close all %tanquem figures anteriors (optatiu)
figure %nova figura
hold on %per fer les dues grafiques sobre la mateixa figura
f=@(x) sin(x);
p3=@(x) x-x.^3/6;
x=-pi:0.01:pi;
y=f(x);
plot(x,y)
y2=p3(x);
plot(x,y2) %tambe podem fer directament "plot(x,y,x,y2)"
(2) Representeu la funció a l'interval , prenent 0.001 com a increment de l'interval d'abscisses Visualment, compteu el nombre de zeros i d'extrems relatius (màxims i mínims) de la funció.
%close all %tanquem figures anteriors (optatiu)
figure %nova figura
hold on
f=@(x) log(x.^2-x+2).*cos(x);
x=-10:0.001:15;
y=f(x);
plot(x,y)
grid %hi ha 8 zeros, 4 maxims i 4 minims