Resolução de equações - Método da Bissecção

Veja neste artigo como desenvolver, em C#, um programa que utiliza o chamado “Método da Bissecção” para encontrar a raíz aproximada de uma função complexa.

Veja neste artigo como desenvolver, em C#, um programa que utiliza o chamado “Método da Bissecção” para encontrar a raíz aproximada de uma função que geralmente necessitaria de um pouco mais de trabalho para ser resolvida da forma convencional, isolando variáveis e realizando operações aritméticas simples.

De fato este artigo é um pouco diferente dos demais existentes no portal no que se refere ao tema. Resolução de equações não é algo comumente visto no meio de programação, banco de dados ou semelhantes. Este tema é mais comum a estudantes e profissionais de engenharia e áreas das ciências exatas. Porém, não quer dizer que não possa chegar ao conhecimento de todos, não é mesmo? E por isso estou compartilhando com vocês.

Suponha que você é um engenheiro eletricista e se depara com um circuito elétrico cuja corrente i é dada por i = 9e^(-t)cos(2̃πt), onde t é dado em segundos. Você precisa determinar em que instante a corrente no circuito será igual a 3 amperes.

Primeiro vamos organizar as equações, se queremos i=3, temos:

9e^(-t)cos(2̃πt) = 3 à 9e^(-t)cos(2̃πt) - 3 = 0

Essa será nossa função f, da qual buscaremos encontrar a raíz:

f(t) = 9e^(-t)cos(2̃πt) - 3

Para termos uma noção de quanto vale t quando i=3, vamos plotar o gráfico da função. Como falamos em tempo, avaliaremos apenas instantes em que t>=0 (no caso, usaremos t de 0s a 1s) e obteremos os seguinte gráfico:


Figura 1. Gráfico da função 9e^(-t)cos(2̃πt) - 3

Observamos que o primeiro instante t em que i=3 está entre 0.1s e 0.2s, mas não temos um valor mais preciso. É aqui que entra o método numérico da bissecção.

Este método tem esse nome por que ele se baseia em intervalos para encontrar uma raiz aproximada de forma iterativa e, a cada iteração, ele secciona o intervalo ao meio, obtendo dois intervalos menores.

Após seccionar o intervalo original, verificamos se a raiz está no primeiro subintervalo ou no segundo. Para fazer essa verificação, analisamos o valor da função no início do intervalo [a,b] e no fim. Se f(a)*f (b)<0 indica que a está antes da raíz e b está depois da raíz, ou seja, a raíz está no intervalo.

Inicialmente, o valor que definimos para a raíz R é o valor médio do intervalo [a,b], ou seja, (a+b)/2. Se esse valor satisfaz nossa necessidade, paramos, senão, continuamos até obter ruma maior precisão.

O algoritmo do método é o seguinte:

Listagem 1: algoritmo do método da bissecção

ENTRADA: Inicio, Fim: reais; Precisão, Iterações: inteiros; VARIÁVEIS: Raiz, Erro, Temp: real; INÍCIO Erro = 1; //Definimos um erro muito grande para iniciar as iterações Cont = 0; ENQUANTO Erro > Precisão E Cont < Iterações //Enquanto não obtivermos a precisão desejada ou enquanto não //atingirmos um número máximo de iteações Temp = Raiz; //Armazenamos o valor anteriormente encontrado Raiz = (Inicio + Fim)/2; Erro = ABS((Raiz - Temp)/Raiz);//Usamos o módulo (valor ABSoluto); SE f(Inicio)*f(Raiz) < 0 //Se essa condição for verdadeira, implica dizer que a raiz está entre //Inicio e Raiz (que é a metade do intervalo), o novo intervalo passa //a ser [Inicio, Raiz] e dentro dele faremos novamente a verificação Fim = Raiz; SENÃO //Senão, a raiz está no segundo subintervalo, e o intervalo passa a ser //[Raiz, Fim] e dentro dele executaremos o processo novamente Início = Raiz; FIM_SE Cont = Cont + 1; //Esse contador é utilizado para fazer um controle do método. //Se dentro de um número máximo de Iterações, não se obtiver um //valor satisfatório, paramos FIM_ENQUANTO FIM

Agora vamos ao C#. Primeiramente definiremos nossa função f como já foi apresentado:

Listagem 2: função f da qual se busca a raiz

private double f(int t) { return 9 * Math.Exp(-1 * t) * Math.Cos(2 * Math.PI * t) - 3; }

E então implementamos o método da bissecção:

Listagem 3: implementação do método da bissecção.

private double Bisseccao(double inicio, double fim, double precisao, int iteracoes) { double Erro = 1; int Cont = 0; double Raiz = inicio; double Temp; while (Erro > precisao && Cont < iteracoes) { Temp = Raiz; Raiz = (inicio + fim) / 2; Erro = Math.Abs((Raiz - Temp) / Raiz); if (f(inicio) * f(Raiz) < 0) fim = Raiz; else inicio = Raiz; Cont++; } return Raiz; }

Como conhecemos um intervalo inicial , podemos usar o método:

Listagem 4: utilizando o método da bissecção

double raiz = Bisseccao(0.1, 0.2, 0.001, 100);

No exemplo, utilizamos o intervalo inicial que encontramos observando o gráfico, [0.1, 0.2], e definimos uma precisão de 0.001, ou seja, não aceitamos um erro superior a isso. Determinamos, ainda, que o número máximo de iterações é 100.

Se executarmos os códigos acima, encontraremos uma raiz aproximadamente 0.1842, mas de fato esse valor não é exato. O C#, bem como outras linguagens de alto nível, não possui uma boa precisão para estes cálculos.

Vale lembrar, ainda, que a função f pode ser modificada, apenas utilizei um exemplo que achei interessante. E para encontrar o intervalo inicial, podemos plotar o gráfico e observar onde a curva intercepta o eixo X.

Bom, esse é apenas um dos métodos numéricos utilizados e é também o mais simples deles. Por hora ficaremos por aqui, espero que gostem.

Até a próxima.

Ebook exclusivo
Dê um upgrade no início da sua jornada. Crie sua conta grátis e baixe o e-book

Artigos relacionados