Cálculo Numérico- UFABC

Método da Bissecção
Um dos métodos numéricos para encontrar raízes de uma função é o Método da Bissecção, um método iterativo para calcular aproximações das raízes de uma equação por meio de bisseções do intervalo inicial.
-
Consiste em tomar dois pontos x0 e x1, de modo que f(x0) e f(x1) tenham sinais contrários.
-
Caso f(x0) ou f(x1) seja igual a 0, a raiz já foi encontrada.
-
Caso contrário, há uma raiz entre os dois pontos escolhidos. Então chama-se de x2 o ponto médio do intervalo [x0, x1].
Caso f(x2) seja igual a zero, x2 é raiz.
Caso contrário, ou f(x2) e f(x0) têm sinais contrários e há uma raiz entre [x2, x0] ou f(x2) e f(x1).
E assim sucessivamente.
O método é fundamentado no Teorema do Valor Médio em que, caso tome-se um c pertencente ao intervalo [a, b], no qual a uma função é contínua e diferenciável:
f(c) = f(b) - f(a) / b -a.
Por se tratar de um método simples, é mais lento que, por exemplo, o Método de Newton-Raphson.Sua convergência é linear, uma vez que a cada iteração o erro absoluto é reduzido pela metade:
|xn - x| ⃔<= |b - a| / 2n (função de iteração para a n-ésima iteração)
Sendo દn o erro absoluto, દn+1 <= દn /2.
Como critério de parada para uma precisão ε, ao se obter um intervalo menor ou igual a ε ou quando for atingido o número máximo de iterações, pode-se considerar tal ponto como raiz.
Gráfico da função do exercício 1, o qual nos dá uma noção de onde está o seu respectivo zero. (Fonte: WolframAlpha)
Segue abaixo o código realizado pelo método da Bissecção:

function raiz=biseccao(def,x0,x1,tol) criando function, (função,valor inicial, valor final, tolerância) --->
f=inline(def);
if f(x0)*f(x1)<0 isolamento da raiz se f(x0)*f(x1) < 0 ,existem raiz(es) de f(x) no intervalo xo x1
x=x0;
while abs(f(x))>tol Repetição enquanto o módulo função não for menor que tolerância
x=(x0+x1)/2;
if f(x0)*f(x)<0
x1=x;
else
x0=x;
end
end
raiz=x;
else
raiz='Não encontrou Valor';
end
No Command Window digite:
biseccao('(3.5*10^7+0.401*(1000/x)^2)*(x-42.7*10^-3)-1.3806503*10^-23*3*10^5',10^-2,10^2,10^-12) ---> (função,valor inicial, valor final, tolerância) vai escolhendo valores X0/X1 até o progrma chegar a um resultado , ) x0 e x1 da biseccção pode ser ponto de partida pra solução dos outros métodos, a verificar...
ans =
0.042700000000000
Método da Falsa Posição
O método da falsa posição é capaz de calcular a solução de uma equação linear definida em um intervalo [a,b]. Dentro desse intervalo existirá um subintervalo que conterá a solução. A ideia do método é ir diminuindo cada vez mais esses subintervalos até que exista um onde a função terá valores opostos, e será então o espaço onde a solução se encontrará.


fprintf('MÉTODO DA FALSA-POSICAO');
f = '35000000*x+401000./x-17122.7./x.^2-1494500'; %funcao do exercicio simplificada e em forma de string
a = -1; %valor inicial do intervalo a ser analisado
b = 1; %valor final do intervalo a ser analisado
tol = 1e-12; %tolerância dada pelo exercício
i = 0; %iteração inicial
imax = 100; %iteração máxima a fim de parar o programa
x = a;
fa = eval(f); %eval transforma a função string em uma função com variável x
x = b;
fb = eval(f);
x = (a * fb - b * fa)/(fb - fa);
fx = eval(f);
c = b - a; %cálculo simples do erro
fprintf('\ni a b x fx erro\n');
fprintf('%i %10f %10f %10f %10f %10f\n', i, a, b, x, fx, c);
while (abs(fx) > tol) && i < imax %condicoes para rodagem do codigo
if fa * fx < 0
b = x;
else a = x;
end;
i = i + 1; %iteracao recebe +1 a cada vez que roda o comando
x = a;
fa = eval(f);
x = b;
fb = eval(f);
x = (a * fb - b * fa)/(fb - fa);
fx = eval(f);
c = b - a;
fprintf('%i %10f %10f %10f %10f %10f\n', i, a, b, x, fx, c);
end;
fprintf('________________________________________________________________');
fprintf('\nA raiz aproximada é: %f\n', x);
fprintf('Quantidade de iterações: %i\n', i);

Método de Newton- Raphson


%o codigo como uma funcao seria function [raiz, res, niter] = newton(fun, der, x0, tol, nmax)
fprintf('MÉTODO DE NEWTON-RAPHSON');
fun = '35000000*x+401000/x-17122.7/x^2-1494500'; %funcao simplificada e definida como string
der = '(35000000*(x^3-0.0114571*x+0.00097844))/x^3';%derivada da funcao em forma de string
x0 = 1; %valor inicial de aproximacao
tol = 1e-12; %tolerancia dada pelo exercicio
nmax = 100; %numero maximo de iteracoes
x = x0;
fx = eval(fun); %tranforma o string da funcao em expressao numerica de variavel x
dfx = eval(der);
niter = 0; %numero da iteracao inicial
delx = tol + 1; %valor de delta x inicial -> x(n+1) - x(n)
fprintf('\ni xi Fxi DFxi Deltaxi\n');
fprintf('%i %f %f %f %.20f\n', niter, x, fx, dfx, delx);
while delx >= tol && niter <= nmax
niter = niter + 1; delx = -fx/dfx;
x = x + delx; delx = abs(delx);
fx = eval(fun);
dfx = eval(der);
fprintf('%i %f %f %f %.20f\n', niter, x, fx, dfx, delx);
end
if niter > nmax
fprintf('ERRO: não convergiu \n');
end
fprintf('________________________________________________________________');
fprintf('\nRaiz =%.10f\nResiduo =%.20f\nIterações = %i\n', x, fx, niter);
return


Nesse exercício, o valor escolhido para E foi -1. Obviamente, para outros valores de E, seriam obtidos outros gráficos e outros zeros para cada função.
Gráfico da função do exercício 2 para E = -1, uma noção de onde seu respectivo zero se encontraria. (Fonte: WolframAlpha)

Método da Bissecção
function [y]=f(x)
y = (-1/x^3)-(1/x^2)+1
endfunction
function bissection(a, b, maximo, tol)
printf('Seja a função y = (-1/x^3)-(1/x^2)+1 \n')
printf('Queremos encontrar os zeros da função \n')
if(f(a)*f(b)>0)
printf('Nada se pode dizer no intervalo [%g,%g]',a,b)
else
while(abs(b-a)>tol*max(a,b))
for k=0:maximo
x = (a+b)/2.;
printf('Com o intervalo [%g,%g] vemos que:\n',a,b)
printf('\nx = %g, x1=%g e x2 = %g',x,f(a),f(b));
if (f(a)*f(x)<0) then
b = x;
printf('\n(V)a = %g, b = %g',a,b);
else (f(x)*f(b)<0)
a = x;
printf('\n(F)a = %g, b = %g',a,b);
end
printf('\n Na %g iteração obtemos que x em [%g,%g]\n',k+1,a,b);
if abs(b-a)<tol then
x = (a+b)/2;
return;
end
end
printf('\nApós %g iterações, a raíz é %g',k+1,x);
end
printf('\nApós %g iterações, a raíz é %g',k+1,x);
end
endfunction
bissection(1,2,100,%eps);
A raiz encontrada :1.32472
O número de interações: 53

Método da Falsa Posição
fprintf('MÉTODO DA FALSA-POSICAO');
f = '-1./x.^3-1./x.^2+1'; %E = -1
a = 1;
b = 2;
tol = eps; %a tolerância usada foi o epsilon da maquina
i = 0;
imax = 100;
x = a;
fa = eval(f);
x = b;
fb = eval(f);
x = (a * fb - b * fa)/(fb - fa);
fx = eval(f);
c = b - a;
fprintf('\ni a b x fx erro\n');
fprintf('%i %.10f %.10f %.10f %.10f %.10f\n', i, a, b, x, fx, c);
while (abs(fx) > tol) && i < imax
if fa * fx < 0
b = x;
else a = x;
end;
i = i + 1;
x = a;
fa = eval(f);
x = b;
fb = eval(f);
x = (a * fb - b * fa)/(fb - fa);
fx = eval(f);
c = b - a;
fprintf('%i %.10f %.10f %.10f %.10f %.10f\n', i, a, b, x, fx, c);
end;
fprintf('________________________________________________________________');
if abs(c) <= eps*max(1,x)
fprintf('\nO numero de iteracoes para que |x(n+1)-x(n)| <= eps*max{1,x} = %i\n', i);
else fprintf('\nO erro não é menor do que |x(n+1)-x(n)| <= eps*max{1,x} para essas iteracoes');
end
fprintf('\nA raiz aproximada é: %f\n', x);
fprintf('Quantidade de iterações: %i\n', i);


Método de Newton- Raphson
%o codigo como uma funcao seria function [raiz, res, niter] = newton(fun, der, x0, tol, nmax)
fprintf('MÉTODO DE NEWTON-RAPHSON');
fun = '-1./x.^3-1./x.^2+1'; %E = -1
der = '(3 + 2*x)./x.^4'; %derivada da função calculada através do WolframAlpha
x0 = 1;
tol = eps;
nmax = 100;
x = x0;
fx = eval(fun);
dfx = eval(der);
niter = 0;
delx = tol + 1;
fprintf('\ni xi Fxi DFxi Deltaxi\n');
fprintf('%i %f %f %f %.20f\n', niter, x, fx, dfx, delx);
while delx >= tol && niter <= nmax
niter = niter + 1; delx = -fx/dfx;
x = x + delx; delx = abs(delx);
fx = eval(fun);
dfx = eval(der);
fprintf('%i %f %f %f %.20f\n', niter, x, fx, dfx, delx);
if abs(delx) <= eps*max(1,x)
fprintf('\nO numero de iteracoes para que |delx| <= eps*max{1,x} = %i\n', niter);
end
end
if niter > nmax
fprintf('ERRO: não convergiu \n');
end
fprintf('________________________________________________________________');
fprintf('\nRaiz =%.10f\nResiduo =%.20f\nIterações = %i\n', x, fx, niter);
return

Conclusões
O método de Newton é o mais eficiente para a aproximação de zeros das funções, dado que, sabendo o intervalo em que a raiz se encontra, o número de iterações para encontrá-la se torna bem menor. Isso se deve a ordem de convergência de cada um dos métodos, enquanto que para os métodos de bissecção e de falsa-posição a ordem é linear, para o método de Newton-Raphson ela é quadrática.