sexta-feira, 1 de julho de 2022

Encontrando "todas" as raízes de uma função conhecida para um dado intervalo.

 

Exemplo de funções com múltiplas raízes.


Muitos problemas envolvem o cálculo das raízes de uma função qualquer. Existem métodos numéricos eficientes para o cálculo dessas raízes, entretanto, esses métodos encontram apenas uma raiz dentro de um intervalo conhecido. Nesta postagem, mostramos como encontrar todas as raízes dentro de um dado intervalo. O método é bem simples e consiste nos seguintes passos:

  • definir um intervalo (x1, x2), com x2 > x1;
  • dividir esse intervalo em N trechos (N > 10), d = (x2-x1)/N
  • varrer esse intervalo fazendo x variar de x1 a x2 com passo d;
  • se $f(x).f(x+d) < 0$, calcular xr dentro deste intervalo e guardar esses valores;
  • usar o método (quase) Newton com esse valor xr para encontrar a raiz próxima a xr.

Note que se $f(x).f(x+d) < 0$, então existe pelo menos uma raiz no intervalo $(x, x+d)$. O valor $xr$ (dentro do intervalo (x, x+d)) pode ser calculado por: 
\[  xr = \frac{(x.abs(f(x+d)) + (x+d).abs(f(x)))}{(abs(f(x)) + abs(f(x+d)))} \]

A derivada de uma função pode ser calculada de forma numérica por:
\[  \frac{df}{dx} = \frac{f(x+h) - f(x-h)}{2h}  \]
sendo $h$ um valor pequeno (ex: 0,00001).

O código Scilab completo para resolver esse problema é:

clc; close(winsid());

function ff=funcf(x) /// exemplo de funções:
      //ff = (2.^x + x).*(x-2.95).*(exp(-(x.*x)/4))+0.5;
    //ff = xd.*xd + exp(-x/2) + sin(x+0.3) - 5;
    //ff = cos(sqrt(abs(15*x))).*exp(-abs(x)/4);
    //ff = sin(x.*sqrt(abs(2*x))).*exp(-abs(x)/4);
    n = (x+3.92).*(x+2.07).*(x-0.66).*(x-3.37);
    d = x.*x + 2;
    ff = n./d;
endfunction

x1 = -4.5;  // definindo o intervalo
x2 = 4.5;
a = x1:0.05:x2;
y = funcf(a);
plot(a,y); xgrid;  // gráfico da função

p = [];
xr = 0;
dd = (x2-x1)/20;
disp('[k, k+dd, k+dd/2, xr]'); 
for k=x1:dd:x2 /// procurando pelas raízes
    y1 = funcf(k);
    y2 = funcf(k+dd);
    if y1*y2 < 0 then 
        xr = (k*abs(y2) + (k+dd)*abs(y1))/(abs(y1) + abs(y2));
        p = [p, xr]; 
        disp([k, k+dd, k+dd/2, xr]); 
    end;
end
//disp(p);

rr = [];
for n=1:max(size(p)) /// calculando as raízes
e=1;
emin = 1e-6;
xk = p(n);
h = 1e-5;
h2 = 2*h;
kk = 0;
while abs(e)>emin
  dff = (funcf(xk+h) - funcf(xk-h))/(h2);
  e = funcf(xk)/dff;
  xk = xk - e; 
  kk = kk + 1; 
  //disp([xk, kk]);
end
rr = [rr; xk, kk];
end
disp(rr);
plot(rr(:,1),rr(:,1)*0,'ro');
xlabel('x'); ylabel('f(x)');
title('Função f(x) e suas raízes');

Nenhum comentário:

Postar um comentário