Escolar Documentos
Profissional Documentos
Cultura Documentos
Londrina
2020
Lista de implementações
2 ZEROS DE FUNÇÕES . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.1 Método da Bissecção . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.1.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
2.2 Método de Newton . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
2.2.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2.3 Método da Secante . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
2.3.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
2.4 Comparação dos métodos . . . . . . . . . . . . . . . . . . . . . . . . . 53
2.5 Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
3 SISTEMAS LINEARES . . . . . . . . . . . . . . . . . . . . . . . . . 59
3.1 Método de Jacobi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
3.1.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.2 Método de Gauss-Seidel . . . . . . . . . . . . . . . . . . . . . . . . . . 72
3.2.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
3.3 Comparação dos métodos . . . . . . . . . . . . . . . . . . . . . . . . . 77
3.4 Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4 INTERPOLAÇÃO . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4.1 Forma de Lagrange . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
4.1.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
4.2 Forma de Newton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
4.2.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
4.3 Forma de Newton-Gregory . . . . . . . . . . . . . . . . . . . . . . . . 102
4.3.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
4.4 Comparação dos métodos . . . . . . . . . . . . . . . . . . . . . . . . . 107
4.5 Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
Introdução
Este material é uma versão preliminar das notas de aula da disciplina de Cálculo
Numérico do professor Edson Luiz Valmorbida da UTFPR-Londrina. Ele foi desenvolvido
com base em diferentes livros e textos indicados ao longo do material e na ementa da
disciplina.
Bons estudos.
Prof. Edson
17
A constante evolução da humanidade traz junto consigo novos problemas dia após
dia, cada um mais complexo que o anterior. Os principais problemas que temos hoje
demandam muito mais do que o cérebro humano daria conta por si só. As ferramentas
computacionais estão presentes no nosso dia-a-dia para tornar a resolução destes problemas
possíveis.
1.1 Introdução
Para cada tipo de problema existe mais de um método numérico disponível. Ge-
ralmente não existe um método melhor que o outro em todos os casos. O que ocorre é
um método ser mais adequado para um problema (dependendo de diversos fatores) e não
ser o mais adequado em outro. Conhecer estes métodos, entender o seu funcionamento e
aplicabilidade, vantagens e desvantagens é o objetivo desta apostila.
1
Que não é o erro cometido ao escrever um código.
20 Capítulo 1. Noções Básicas Sobre Erros
• Sistema Vigesimal: foi utilizada pelos maias, bascos e normandos. Utiliza 20 algaris-
mos e pode ser percebido, por exemplo, na língua francesa e dinamarquesa.
• Sistema Binário: com apenas 2 algarismos (0 e 1), este sistema é utilizado em lógica
e na computação pois remete a noções de verdadeiro e falso ou ligado e desligado.
AVISO: Neste capítulo estaremos interessado na relação entre o sistema decimal, usual à
nós, e o sistema binário, base para quase todos os computadores atuais. Na computação,
cada algarismo binário recebe o nome de bit.
Para entender como a conversão entre as bases é feita precisamos olhar para como
os números são representados em uma base. Por exemplo, no sistema decimal escrevemos:
Isto é, o dígito da unidade é multiplicado pela base (10) elevada a 0 e os demais dígitos
vão sendo multiplicados por potências cada vez maiores. Da mesma forma, para número
não-inteiros usamos as potências negativas:
1.2.1 Binário→Decimal
Utilizamos um índice com o valor da base no número que está escrito para denotar
em qual base ele está representado. Isso evita confundir o número (100)(10) (cem) do
número (100)(2) (quatro). Por padrão, se um número não possui índice indicando em qual
base ele está podemos assumir que esta base é a 10.
Exemplo 1.1 Considere o número 100011(2) . Para convertê-lo para a base 10 fazemos:
1 × 25 + 0 × 24 + 0 × 23 + 0 × 22 + 1 × 21 + 1 × 20 =
= 32 + 0 + 0 + 0 + 2 + 1 = 35.
Exemplo 1.2 Considere o número (110, 1011)(2) . Convertendo para a base 10 obtemos:
1 1 1 107
=4+2+0+ +0+ + = = 6, 6875.
2 8 16 16
Portanto, o número (110, 1011)(2) na base 10 é 6, 6875(10) .
1.2.2 Decimal→Binário
Com a parte inteira, dividimos sucessivamente os quocientes por 2 até que ele seja
0. Com a parte decimal, multiplicamos a parte a direita da vírgula por 2 até que não sobre
nada.
Exemplo 1.3 Considere o número 25. Como ele possui apenas parte inteira, precisamos
dividi-lo por 2 até que o quociente remanescente seja 0. Assim, A representação na base 2
é formada pelos restos obtidos na divisão lidos de baixo para cima. Neste exemplo, temos
25(10) = 11001(2) . Fazendo o processo inverso (da seção anterior) vemos que a conversão
está correta.
22 Capítulo 1. Noções Básicas Sobre Erros
1. Nos perguntamos qual a maior potência de 2 que é menor que 25. Nesta caso, é 4
pois 24 = 16 < 25 e 25 = 32 > 25.
3. Como 23 = 8, resta 9 − 8 = 1.
4. Repetimos o processo mais uma vez e vemos que 20 = 1 não deixando nenhum resto.
Por isso o processo é concluído.
Assim,
25 = 24 + 23 + 20 = 1 × 24 + 1 × 23 + 0 × 22 + 0 × 21 + 1 × 20
• Deste resultado, a parte inteira será o primeiro dígito do número na base 2 e a parte
fracionária é novamente multiplicada por 2;
• O processo é repetido até que a parte fracionária do último produto seja igual a zero.
1.2. Sistemas de Numeração e Conversão entre Base 23
Exemplo 1.4 Vamos escrever o número 0, 1875 na base 2. Seguindo os passos indicados
temos:
0, 1875 × 2 = 0, 375
0, 375 × 2 = 0, 75
0, 75 × 2 = 1, 5
0, 5 × 2 = 1, 0
A primeira vista o procedimento acima parece simples, mas na verdade será finito
apenas quando o número dado for uma potência negativa de 2. Nos demais casos teremos
uma situação como no exemplo a seguir.
0, 6 × 2 = 1, 2
0, 2 × 2 = 0, 4
0, 4 × 2 = 0, 8
0, 8 × 2 = 1, 6
0, 6 × 2 = 1, 2
.. ..
. .
Este processo não é finito e os dígitos se repetem formando uma dízima periódica.
Assim, podemos escrever que 0, 6 = 0, 1001(2) .
Por exemplo, na base 10 o número 17, 23 pode ser escrito como 0, 1723 × 102 na
notação científica. Já na base 2 o número 101, 11(2) pode ser escrito como 0, 10111(2) × 23
(11)(2)
ou ainda, 0, 10111(2) × (10)(2) .
0, d1 d2 . . . dj ×β e
| {z }
M antissa
onde:
Exemplo 1.6 Considere o número 25, 1875. Já vimos, nos exemplos da seção anterior,
que a sua representação na base 2 é 11001, 0011(2) . Passando este número na base 2 para
(101)(2)
a notação científica, obtemos: 0, 110010011(2) × 25 = 0, 110010011(2) × (10)(2) .
• Os 4 dígitos restantes permitem armazenar qualquer número inteiro entre −15 e 15.
Como pode ser visto no exemplo acima, diversos problemas podem ocorrer ao
representar um número no sistema de ponto flutuante finito:
1. Existe uma quantidade finita de números que podem ser representados em uma
máquina.
2. Existe um número máximo e um mínimo que podem ser armazenados. Isso pode
causar problemas chamados overflow e underflow.
3. Diferente do conjunto dos número reais, existe um número que pode ser chamado de
menor número positivo.
4. Se precisarmos de um número que seja entre 0 e este menor número positivo, pode
ser que o sistema “arredonde” para zero algo que não é nulo.
5. A grande maioria dos número precisam ser arredondados (como é o caso do 0.6).
Se houver uma dízima ou apenas a necessidade de mais dígitos do que o limite da
mantissa, o sistema trunca a representação alterando o seu valor.
26 Capítulo 1. Noções Básicas Sobre Erros
A seguir citamos alguns exemplos onde os efeitos numéricos podem ser percebidos.
1.5 Exercícios
c) 0, 25 f) 27 i) 1024
Resposta: a) 10000001(2) ; b) 100011001(2) ; c) 0, 01(2) ; d) 0, 1001(2) ; e) 10101, 0110(2) .
5. A função f (x) = ex pode ser calculada usando sua expansão em série de Taylor:
1 2 1 3 ∞
xi
ex = 1 + x + x + x + ··· = 1 +
X
.
2! 3! i=1 i!
Se usarmos a soma parcial da série acima até um valor n obteremos uma aproximação
para ex .
x+y =1
7. Escreve um script de teste para obter a precisão do seu computador. Para isso, use
o algoritmo abaixo.
a = 1;
enquanto 1 + a ∼= 1
a = a/2;
fim
disp(2 ∗ a)
O algoritmo acima começa com o número 1 na variável a e, a cada repetição, divide
o valor da variável pela metade. Em aritmética infinita sabemos que jamais deveria
ocorrer o caso 1 + a == 1 pois a sempre será positivo. Porém, no computador
isso ocorrerá quando a atingir a precisão máxima da máquina. Compare o valor
encontrado a variável eps.
31
2 Zeros de Funções
O primeiro problema que trataremos nesta apostila possui uma natureza muito
simples, porém engana-se quem pensa que ele é de fácil solução. De fato, diversos métodos
e adaptações foram propostos para solucioná-lo. O problema ao qual nos referimos é o de
encontrar raízes de uma função real, isto é, encontrar os números reais a para os quais
f (a) = 0, para uma função f dada.
Observação 2.1 A partir deste ponto iremos assumir que a função analisada é contínua.
• Se f (x) = ax2 + bx + c for um polinômio de grau 2 então as raízes reais são dadas
pela fórmula de Báskara: √
−b ± b2 − 4ac
x= ,
2a
desde que, é claro, o discriminante seja não negativo.
Não iremos tratar neste texto o problema de encontrar uma aproximação inicial.
De modo geral, isso é feito a partir de conhecimentos prévios do problema (no caso de
33
Definição 2.2 Um método iterativo consiste em uma sequência de instruções que são
executadas passo a passo e que são repetidas em ciclos. A execução de um ciclo recebe
o nome de iteração. Cada iteração utiliza resultados das iterações anteriores e efetua
determinados testes que permitem verificar se foi atingido um resultado próximo o suficiente
do resultado esperado, esta verificação recebe o nome de critério de parada.
Início
Dados Iniciais
k=1
Calcular uma
nova aproximação Método Numérico
Critério de Parada
Esta aproximação
está suficientemente Cálculos
próxima da raiz sim finais
exata?
Fim
não
k=k+1
É claro que existem diversas estratégias para resolver o problema proposto. Neste
texto iremos apresentar 3 métodos iterativos clássicos que apresentam diferentes e impor-
tantes estratégias para abordar o problema:
|xk+1 −xk |
• Erro relativo: |xk |
≤ ε. Mesmo princípio do erro absoluto. A vantagem do erro
relativo é que ele leva em consideração a magnitude das aproximações envolvidas,
isto é, não faz iterações desnecessárias quando a raiz é um número muito grande e
nem para cedo demais quando a raiz é um número muito pequeno.
Não entraremos em muitos detalhes sobre como obter uma aproximação inicial,
pois na maioria dos exercícios que veremos esta informação inicial é dada. Além disso, em
problemas práticos, frequentemente esta informação é sugerida pelo contexto do próprio
problema.
Teorema 2.1 (Teorema do Valor Intermediário) Seja f uma função contínua num
intervalo [a, b]. Se f (a) · f (b) < 0, então existe pelo menos um ponto entre a e b que é zero
de f (x).
Uma função que satisfaz a hipótese f (a)·f (b) < 0 do teorema do valor intermediário
(TVI) possui essencialmente duas possibilidades, como mostra a figura 4. Ou seja, f (a) e
f (b) precisam ter sinais trocados para que a desigualdade seja válida2 .
É possível ainda que o gráfico da função cruze o eixo x mais de uma vez. Isso não
invalida o resultado pois o teorema apenas garante a existência de ao menos uma raiz da
função f . De fato, algum resultados decorrem do teorema ou tem demostração análoga:
2
Aqui não estamos considerando o caso de um deles ser igual a zero pois, neste caso, já teríamos uma
solução para o problema e isso é muito improvável de ocorrer por causa das imprecisões numéricas
discutidas no capítulo 1.
36 Capítulo 2. Zeros de Funções
i) Se f (a) · f (b) < 0, então existe um número ímpar de raízes no intervalo (a, b).
ii) Sob as hipóteses do teorema anterior, se f 0 (x) existir e preservar o sinal em (a, b),
então este intervalo contém um único zero de f (x).
iii) Se f (a) · f (b) > 0, então existe um número par de raízes ou nenhuma raiz no intervalo
(a, b).
Se f é uma função contínua num intervalo [a, b] tal que f (a) · f (b) < 0 (ou seja,
satisfaz as hipóteses do TVI), como na figura 5, então denotamos a0 = a e b0 = b.
Caso f (a0 ) · f (x0 ) < 0 então concluímos a primeira iteração escolhendo o novo
intervalo como [a1 , b1 ] = [a0 , x0 ]. Caso contrário, escolhemos o novo intervalo é [a1 , b1 ] =
[x0 , b0 ].
2.1. Método da Bissecção 37
ak + b k
xk = (2.1)
2
em que ak e bk são escolhidos como descrito.
O texto acima nos dá uma boa ideia de como construir o algoritmo para o método,
mas antes de discutirmos isso vamos fazer um exemplo com uma função específica.
Exemplo 2.2 Considere a função f (x) = x2 − 3 e o intervalo [a, b] = [1, 2]. Obtenha uma
aproximação para a raiz de f utilizando o critério de parada |f (xk )| ≤ 0.01.
f (x0 ) = −0.75,
f (b0 ) = f (2) = 1.
Como |f (x0 )| = 0.75 > 0.01, o critério de parada não foi atingido e precisamos
continuar as iterações. O próximo passo é analisar os sinais:
Portanto, o TVI nos garante que uma raiz está no intervalo [x0 , b0 ]. Com isso, o
novo intervalo é [a1 , b1 ] = [1.5, 2]. A figura acima mostra esta iteração.
38 Capítulo 2. Zeros de Funções
f (x1 ) = 0.0625,
f (b1 ) = f (2) = 1.
Assim, o novo intervalo é [a2 , b2 ] = [1.5, 1.75] pois é nele onde temos a certeza da
presença de uma raiz. A figura acima mostra esta iteração.
f (x2 ) = −0.359375,
f (x3 ) = −0.15234375,
f (x4 ) = −0.045898438,
f (x5 ) = 0.008056641,
Como |f (x5 )| = 0.008056641 < 0.01, o critério de parada é satisfeito e não precisamos
prosseguir.
40 Capítulo 2. Zeros de Funções
Assim, a aproximação encontrada pelo método foi x5 = 1.734375 sendo que a raiz
√
exata é 3 ≈ 1.732050807568877. A tabela 1 resume as iterações feitas.
k ak bk xk |f (xk )|
0 1 2 1.5 0.75
1 1.5 2 1.75 0.0625
2 1.5 1.75 1.625 0.3593
3 1.625 1.75 1.6875 0.1523
4 1.6875 1.75 1.71875 0.0458
5 1.71875 1.75 1.734375 0.0081
Observação 2.2 A função do exemplo acima traz uma aplicação interessante dos métodos
√
para zero de função. Já sabíamos que as raízes da função são ± 3. Portanto, ao aproximar
√
a raiz dela estamos aproximando o valor de 3. Podemos fazer isso com qualquer número
inteiro positivo e obter uma aproximação para a sua raiz quadrada.
2.1.1 Implementação
Assim, faremos uma condição do tipo “Enquanto o critério de parada não for satis-
feito, faça uma iteração do método”. Para exemplificar, nesta implementação utilizaremos
o mesmo critério de parada do exemplo apresentado, isto é, |f (xk )| < T OL, em que TOL
representará a tolerância desejada para a aproximação3 .
Como queremos tornar o código mais abrangente possível, a tolerância TOL será
posta como variável de entrada. Seria possível incluir a expressão do critério de parada
como variável de entrada, porém não faremos pois isso tem algumas sutilezas.
Além das informações para os critérios de parada, precisamos é claro das informações
do problema. No caso do método da bisseção, precisamos da função f e dos extremos do
intervalo inicial a e b. Com isso, podemos começar a construir o esqueleto do algoritmo:
Como pode ser visto, utilizamos duas variáveis de saída x e k. A primeira, corres-
ponde a aproximação encontrada pelo método. Note que não indexamos a variáveis x, isso
foi feito para simplificar o código. É possível tornar x um vetor com todas as iterações
caso desejemos com algumas poucas alterações. A segunda variável é um contador para
o número de iterações. Esta costuma ser uma informação interessante de se observar e
comparar com outros métodos.
• Só precisamos verificar uma das desigualdades para f (ai )f (xi ) e f (xi )f (bi ). Isso
ocorre pois se sabemos o sinal de um dos produtos, o outro deve obrigatoriamente
ter o sinal oposto.
A frase “Caso f (a0 ) · f (x0 ) < 0 então concluímos a primeira iteração escolhendo
o novo intervalo como [a1 , b1 ] = [a0 , x0 ]. Caso contrário, escolhemos o novo intervalo é
[a1 , b1 ] = [x0 , b0 ].” utilizada na apresentação do método indica a estrutura do código.
42 Capítulo 2. Zeros de Funções
x = (a + b)/2;
se f (a) ∗ f (x) < 0
b = x;
senão
a = x;
fim
Algoritmo 1: Método da bisseção.
Agregando este pseudocódigo (já traduzido para o MATLAB) ao código, podemos
concluí-lo como abaixo (com uma pequena adaptação para coerência):
22
23 x = ( a + b ) /2;
24 k = k +1;
25 end
• Se o intervalo inicial for grande e/ou se for pequeno, o número de iterações tende a
ser consideravelmente maior do que os demais;
Seja f uma função contínua cuja raiz chamaremos de x. Tomamos uma aproximação
inicial x0 e traçamos a reta y = L0 (x) tangente ao gráfico de f no ponto (x0 , f (x0 )), veja
a figura 6.
O ponto que procuramos é (x1 , 0) pois está sobre o eixo x. Substituindo na expressão
obtemos:
f (x0 )
⇒x1 = x0 − .
f 0 (x0 )
2.2. Método de Newton 45
f (xk )
xk+1 = xk − . (2.2)
f 0 (xk )
Observação 2.3 Existe uma segunda forma de obter esta mesma expressão e que abre
portas para um conjunto de métodos. Podemos escrever a série de Taylor da função f
e truncá-la no segundo termo (onde está a primeira derivada) ou em qualquer outro
termo. Estes métodos são chamados de métodos baseados em série de Taylor, porém tem
aplicabilidade mais específica.
Exemplo 2.3 Vamos procurar uma aproximação para uma raiz da função f (x) = x2 +x−6
usando como aproximação inicial x0 = 1.5. O critério de parada que vamos utilizar é
|f (xk )| ≤ 10−4 .
• Iteração k = 1:
f (x1 )
⇒x2 = x1 − = 2.000762195121951.
f 0 (x1 )
Para esse ponto temos f (x2 ) = 0.003811556551161 e |f (x2 )| > 10−4 .
• Iteração k = 2:
f (x2 )
⇒x3 = x2 − = 2.000000116152868.
f 0 (x2 )
Para esse ponto temos f (x3 ) = 5.807643539412766e − 07 e |f (x3 )| > 10−4 .
k xk f (xk )
0 1.5 −2.25
1 2.0625 0.31640625
2 2.000762195121951 0.003812
3 2.000000116152868 5.80764e − 07
O que o teorema acima diz é que se a aproximação inicial estiver suficiente próxima
de uma raiz (dentro do intervalo [p − δ, p + δ]) então o método irá convergir e se estiver for
não há garantia. O problema é que não há como saber se a aproximação inicial disponível
está dentro deste intervalo.
2.2.1 Implementação
k = 0;
enquanto Critério de Parada
x=x− f (x)
f 0 (x)
;
k = k + 1;
fim
Algoritmo 2: Método de Newton.
O código do método de Newton fica como abaixo.
14 k = 0;
15 while abs ( f ( x ) ) > TOL && k <= kmax
16 x = x - f ( x ) / df ( x ) ;
17 k = k +1;
18 end
f (x) − f (xk )
f 0 (xk ) = lim .
x→xk x − xk
f (xk−1 ) − f (xk )
f 0 (xk ) ≈ .
xk−1 − xk
Como nenhum destes pontos satisfaz o critério de parada vamos calcular a próxima
aproximação:
f (x1 )(x1 − x0 )
x2 = x1 − = 2.14285714.
f (x1 ) − f (x0 )
Para esse ponto temos f (x2 ) = 0.73469388 e |f (x2 )| > 10−4 .
• Iteração k = 2:
f (x2 )(x2 − x1 )
x3 = x2 − = 1.98461538.
f (x2 ) − f (x1 )
Para esse ponto temos f (x3 ) = −0.07668639 e |f (x3 )| > 10−4 .
• Iteração k = 3:
f (x3 )(x3 − x2 )
x4 = x3 − = 1.99957137.
f (x3 ) − f (x2 )
Para esse ponto temos f (x4 ) = −0.00214298 e |f (x4 )| > 10−4 .
• Iteração k = 4:
f (x4 )(x4 − x3 )
x5 = x4 − = 2.00000132.
f (x4 ) − f (x3 )
Para esse ponto temos f (x5 ) = 6.6153e − 06 e |f (x5 )| < 10−4 .
k xk f (xk )
0 1.0 −4
1 1.5 −2.25
2 2.14285714 0.73469388
3 1.98461538 −0.07668639
4 1.99957137 −0.00214298
5 2.00000132 6.6153e − 06
• Não necessitamos calcular f 0 (x) como desejávamos (o que é considerado uma vanta-
gem);
2.3.1 Implementação
x0 x1 x2 x3 x4 ···
k = 1 x0 x1 x2
↓ ↓
k=2 x0 x1 x2
↓ ↓
k=3 x0 x1 x2
.. .. .. ..
. . . .
1 x0 = x1 ;
2 x1 = x2 ;
k = 1;
enquanto Critério de Parada
f (x1)(x1 − x0)
x2 = x1 − ;
f (x1) − f (x0)
x0 = x1;
x1 = x2;
k = k + 1;
fim
Algoritmo 3: Método da Secante.
As variáveis de entrada e saída do código serão análogas as do método de Newton e
bisseção. Neste caso, além da função f, da tolerância TOL e do número máximo de iterações
kmax, precisamos das duas aproximações iniciais x0 e x1.
A variável de saída com a aproximação final encontrada pode ser tanto x1 quanto
x2 pois elas possuem a mesma informação armazenada ao final de cada iteração. No
entanto, optamos por usar x1 para o caso excepcional de o critério de parada ser atingido
já na primeira iteração e o código não entrar no while. Isso causaria a variável x2 não
existir e, portanto, causando um erro na variável de saída.
No critério de parada, utilizamos abs(f(x1))> TOL && k <= kmax pois, como
dito, as variáveis x1 e x2 possuem a mesma informação ao final de cada iteração. Porém,
antes de entrar no while, a variável x2 não existe.
2.4. Comparação dos métodos 53
deste método é ter uma convergência lenta em relação aos demais, precisando de muito
mais iterações para atingir uma boa precisão. Outro ponto ruim deste método é que ele
não pode ser generalizado diretamente para funções de várias variáveis.
Além dos três métodos apresentados neste capítulo, alguns métodos clássicos são:
• Método pégaso;
• Método de Muller;
2.4. Comparação dos métodos 55
• Método de Steffensen.
56 Capítulo 2. Zeros de Funções
2.5 Exercícios
x -∞ −100 −10 −3 0 1 2 3 50 ∞
f (x) − − − + + − − + + +
Sabendo que a função que fornece esse dados é contínua, assinale a alternativa
verdadeira usando o TVI.
b) f (x) = x3 − 9x + 3 com x0 = 0 e x1 = 1.
√
7. Utilize os 4 métodos estudados para aproximar o valor de 2 (quem é a função f ?).
Faça 3 iterações com cada método. Para isso, utilize:
2.5. Exercícios 57
8. Explique com suas palavras os pontos fortes e fracos dos métodos estudados.
10. Considere a função f (x) = e−x − cos(x). Aplique os quatro métodos estudados com
2
d) Secante: Use x0 = 1 e x1 = 2.
a) sen(x) = 0;
b) cos(x) + 1 = 0;
13. Escreva um script no MATLAB que usa as functions apresentadas neste capítulo
para resolver as questões acima nas quais o critério de parada usa |f (xk )| < T OL.
Altere as implementações de modo que todas as iterações sejam exibidas (e não
apenas a última).
14. Implemente uma versão das functions dos métodos no qual o critério de parada
muda de |f (xk )| < T OL para |xk+1 − xk | < T OL. Compare os resultados obtidos
para algum problema teste.
15. Escreva um script no MATLAB que resolva a questão 10 com as informações dadas e
exiba os resultados no mesmo formato. OBS: Lembre-se de alterar as implementações
(faço outros arquivos de function) de modo que utilize o critério de parada correto.
Implementa uma function para o método de Newton para este caso e aplique-o para
a função F (x, y) = (10 − x2 − y, 15 − ex − y). Use (x0 , y0 ) = (2, 7) e T OL = 1e − 4.
Use como critério de parada norm(F(x,y))< TOL.
59
3 Sistemas Lineares
Observação 3.1 Em todos os casos deste capítulo estaremos assumindo que a matriz do
sistema tem determinante diferente de zero e, portanto, o sistema tem exatamente uma
única solução.
1
Hoje já ultrapassou-se a barreira de sistemas de dimensão um bilhão de equações e um bilhão de
incógnitas para problemas de grande porte. Não tente criar uma matriz desse tamanho no MATLAB,
seria necessário 7.45 × 109 Gb para alocá-la.
60 Capítulo 3. Sistemas Lineares
.. (3.1)
.
+ an2 x2 + · · · + ann xn = bn
an1 x1
1
x1 = (b1 − (a12 x2 + a13 x3 + · · · + a1n xn ))
a11
1
= (b2 − (a21 x1 + a23 x3 + · · · + a2n xn ))
x2
a22
..
.
1
= (bn − (an1 x1 + an2 x2 + · · · + an(n−1) x(n−1) ))
xn
ann
através da expressão:
1
xk+1 = (b1 − (a12 xk2 + a13 xk3 + · · · + a1n xkn ))
1
a11
1
= (b2 − (a21 xk1 + a23 xk3 + · · · + a2n xkn ))
k+1
x2
a22 (3.2)
..
.
1
xk+1 = (bn − (an1 xk1 + an2 xk2 + · · · + an(n−1) xk(n−1) ))
n
ann
Ou seja, no método de Jacobi usamos as informações da iteração k (no lado direito) para
obter a iteração k + 1.
Exemplo 3.1 Problema: Aproximar a solução do sistema linear
10x1 + 2x2 + x3 =7
x1 + 5x2 + x3 = −8
2x1 + 3x2 + 10x3 =6
0.7
pelo método de Jacobi fazendo 5 iterações. Use x0 = −1.6 .
0.6
1 1
x11 = (7 − (2x02 + x03 )) = (7 − (2 × (−1.6) + 0.6)) = 0.96
10 10
1 1
x12 = (−8 − (x1 + x3 ))
0 0
= (−8 − (0.7 + 0.6)) = −1.86
5 5
1 1
= (6 − (2x01 + 3x02 )) = (6 − (2 × 0.7 + 3(−1.6))) = 0.94
x13
10 10
0.96
Com isso, obtemos x1 = −1.86 . A iteração seguinte usa x1 para obter x2 da mesma
0.94
62 Capítulo 3. Sistemas Lineares
0.9994 0.99792 1.000236
x3 = , x4 = −1.99956 , x5 = −1.998936 .
−1.9888
0.9984 0.99676 1.000284
No exemplo anterior foi pedido que fizéssemos 5 iterações. Porém, existem critérios
de paradas mais adequados para este tipo de problema. A maioria deles são análogos aos
do capítulo 2:
Observação 3.3 Nos códigos que implementaremos usaremos este último critério pois é
mais simples de fazê-lo. Porém, o custo computacional dela é bem mais elevado que os
dois primeiros.
Como vimos no capítulo anterior, nem todo método iterativo é globalmente con-
vergente. Então, é natural nos questionarmos sobre a convergência do método de Jacobi.
Existem resultados mais precisos, porém aqui nos limitaremos em um que é mais palpável
apesar de ser apenas uma condição suficiente para a convergência.
Definição 3.1 Dizemos que uma matriz é diagonal dominante se, para todas as linhas, a
soma em módulo dos elementos da matriz fora da diagonal for menor que o módulo do
elemento na diagonal. Em outras palavras, uma matriz é diagonal dominante se
n
X
|akj | < |akk |, ∀ k ∈ {1, . . . , n}.
j=1 j6=k
Teorema 3.1 (Critério das Linhas) Seja o sistema linear Ax = b. Se A for diagonal
dominante então o método de Jacobi gera uma sequência {xk } que converge para a solução
do sistema dado, independente da escolha da aproximação inicial x0 .
3.1. Método de Jacobi 63
O critério das linhas nos diz que, para ter a garantia da convergência do método de
Jacobi basta verificarmos que a matriz do sistema é diagonal dominante. Caso isso ocorra,
não importa qual for a aproximação inicial o método irá convergir. O que o método não
diz é o que ocorre com matrizes que não são diagonais dominantes. De fato, se a matriz
não for diagonal dominante então o método pode convergir ou divergir.
Neste caso, como uma das linhas não satisfez a desigualdade a matriz não é diagonal
dominante e não podemos garantir a convergência do método. No entanto, sabemos que
podemos trocar linhas de um sistema linear2 e preservamos a solução dele e isso nos
permite trocar as linhas 3 e 4 do sistema. Com isso, mudamos quem é o elemento da
diagonal e a matriz se tornará diagonal dominante.
Portanto, a matriz original não é diagonal dominante, mas pode ser transformada
em uma que seja.
(L + D + U )x = b
⇒ Dx = −(L + U )x + b.
2
Não podemos esquecer de trocar as linhas correspondentes no vetor do lado direito também.
3.1. Método de Jacobi 65
x = −D−1 (L + U )x + D−1 b.
Assim como feito na forma escalar do método, usamos do lado direita da igualdade
acima a iteração k para obter, do lado esquerdo, a iteração k + 1. Dessa forma, o método
de Jacobi matricial pode ser escrito como:
É importante perceber que a forma (3.3) é igual a (3.2). De fato, você pode perceber
que em (3.2) temos, para cada linha, a soma dos elementos da linha da matriz multiplicando
o vetor xk exceto com o elemento da diagonal. Isso ocorre também em (3.3) pois L + U é
exatamente igual a A, porém com os elementos da diagonal iguais a zero (pois estes estão
em D).
3.1.1 Implementação
n
aij xkj .
X
j=1
j6=i
Isto é, somamos a linha i da matriz A multiplicada pelo vetor xk com exceção do elemento
66 Capítulo 3. Sistemas Lineares
da diagonal (quando i == j). Este trecho do algoritmo pode ser escrito da seguinte forma:
para i = 1 até n
soma = 0 ;
para j = 1 até n
se i 6= j
soma = soma + aij · xj ;
fim
fim
yi = (bi − soma)/aii ;
fim
Um detalhe muito importante neste algoritmo é que não poderíamos fazê-lo sem a
variável y, ou seja, fazendo xi = (bi − soma)/aii . Isso porque se fizéssemos teríamos, para
i==1 a variável x teria sua primeira componente sobrescrita pela informação da iteração
k + 1 e quando fazemos o caso i == 2 precisamos da informação da iteração k, que teria
sido perdida.
Para concluir o algoritmo temos que incluir o trecho acima dentro de loop de
repetição (pois estamos num método iterativo) para realizar as iterações. Além disso,
precisamos incluir um contador de iterações e atualizar a variável x para que ela receba a
informação que está na variável y e que será utilizada na iteração posterior. O primeiro
algoritmo é apresentado em 4.
Tendo o esboço do algoritmo passamos agora a pensar no código que será imple-
mentado. O critério de parada que será imposto é similar aos do capítulo anterior, isto é,
uma tolerância no erro da aproximação e um limitante no número de iterações. Similar ao
que foi feito nas implementações do capítulo 2 onde tínhamos o critério abs(f(x))> TOL,
aqui teremos norm(b-A*x)> TOL para calcular o erro kb − Axk.
k = 0;
enquanto <Critério de Parada>
para i = 1 até n
soma = 0 ;
para j = 1 até n
se i 6= j
soma = soma + aij · xj ;
fim
fim
yi = (bi − soma)/aii ;
fim
x = y;
k = k + 1;
fim
Algoritmo 4: Método de Jacobi - forma escalar.
O código 3.1 apresenta a implementação desta primeira forma escalar. Note que
incluímos ainda duas linhas. A linha n = length(b); serve para termos a dimensão do
sistema que foi recebido como variável de entrada e a linha y = zeros(n,1); garante que
o vetor y seja uma coluna e não uma linha (isso causaria problema quando fizéssemos A*x
no critério de parada).
Ou seja, ao invés de “somar só o que queremos” podemos “somar todos os termos e subtrair
os que não queremos”. O código 3.2 mostra a implementação com esta alteração3 .
3
Só essa mudança implica em uma economia média de 1/3 no tempo de execução para matrizes
1000 × 1000. Para dimensões maiores a economia aumenta.
3.1. Método de Jacobi 69
Ainda pensando nas melhorias possíveis, você pode notar que o trecho
1 soma = 0;
70 Capítulo 3. Sistemas Lineares
2 for j = 1: n
3 soma = soma + A (i , j ) * x ( j ) ;
4 end
nada mais é do que a multiplicação da linha i da variável A pelo vetor x. Portanto, podemos
usar o conceito de vetorização para eliminar este for do código. A implementação 3.3
mostra como fica este código.
24 end
Poderíamos continuar melhorando o código, porém vamos parar por aqui e ver a
forma matricial que, na prática, é melhor que as 3 que já apresentamos.
1 D = diag ( A ) ; % D eh um vetor .
2 invD = 1./ D ;
3 F = - diag ( invD ) *( A - diag ( D ) ) ;
4 g = diag ( invD ) * b ;
Tendo F e g, resta apenas fazer as iterações do método. Neste caso, nem a variável
n e nem y precisam ser criadas pois a iteração é feita de uma única vez. O código mostra
a implementação do método de Jacobi na forma matricial.
9 % SAIDA :
10 % x - aproximacao final encontrada .
11 % k - numero de iteracoes realizadas .
12 function [x , k ] = metJacobiMat (A ,b ,x , TOL , kmax )
13
14 k = 0;
15 D = diag ( A ) ; % D eh um vetor .
16 invD = 1./ D ;
17 F = - diag ( invD ) *( A - diag ( D ) ) ;
18 g = diag ( invD ) * b ;
19
20 while norm (b - A * x ) > TOL && k <= kmax
21 x = F*x + g;
22 k = k +1;
23 end
Observação 3.4 Para sistemas de ordem 1000, a forma matricial gasta cerca de 1/4 do
tempo da primeira forma escalar 3.1.
que utilizamos a iteração k para obter a iteração k + 1. Por causa disso, do lado direito
aparece apenas a iteração k. No entanto, como estas linhas são sempre calculadas indi-
vidualmente em sequência, o valor de xk+1
1 já é conhecido quando vamos calcular xk+1
2 ,
1
xk+1 = (b1 − (a12 xk2 + a13 xk3 + · · · + a1n xkn ))
1
a11
1
xk+1 = (b2 − (a21 xk+1 + a23 xk3 + · · · + a2n xkn ))
2 1
a22
1
x3k+1
= (b3 − (a31 xk+1
1 + a32 xk+1
2 + · · · + a3n xkn )) (3.4)
a33
..
.
1
xk+1 = (bn − (an1 xk+1 + an2 xk+1 (n−1) ))
+ · · · + an(n−1) xk+1
n 1 2
ann
0.7
pelo método de Gauss-Seidel fazendo 5 iterações. Use x0 = −1.6 .
0.6
1
xk+1 = (7 − (2xk2 + xk3 ))
10
1
1
k+1
x2 = (−8 − (xk+1 + xk3 ))
5 1
1
= (6 − (2xk+1 + 3xk+12 ))
xk+1
3
10 1
74 Capítulo 3. Sistemas Lineares
0.96
Com isso, obtemos x = 1
−1.912 .
A iteração seguinte usa x1 para obter x2 da
0.9816
mesma forma:
1 1
x21 = (7 − (2x12 + x13 )) = (7 − (2 × (−1.912) + 0.9816)) = 0.98424
10 10
1 1
x22 = (−8 − (x21 + x13 )) = (−8 − (0.98424 + 0.9816)) = −1.993168
5 5
1 1
= (6 − (2x21 + 3x22 )) = (6 − (2 × 0.98424 + 3(−1.993168))) = 1.0011024
x23
10 10
0.99852336 0.99995774 1.000007
x = 3
= =
4 5
−1.9999252 ,x −2.0000461 ,x −2.0000059 .
1.0002729 1.0000223 1.0000004
No que diz respeito a convergir ou não, o critério das linhas visto para o método de
Jacobi também se aplica ao método de Gauss-Seidel. Isto é, se a matriz do problema for
diagonal dominante então o método irá convergir. Além desse critério, podemos analisar os
autovalores da matriz A para ter uma condição necessária e suficiente para a convergente
(todos os autovalores positivos implica em convergência). Um último critério que pode ser
usado chama-se critério de Sassenfeld. Apesar de ser apresentado em diversos livros, não
iremos vê-lo ou utilizá-lo aqui.
3.2. Método de Gauss-Seidel 75
(L + D + U )x = b
⇒ (L + D)x = −U x + b.
É um pouco mais complicado ver que a expressão (3.5) coincide com (3.4), mas
não impossível.
3.2.1 Implementação
Para a forma matricial vamos usar a function tril que extrai a matriz L + D de
A, isso simplifica alguns passos.
5 % A - matriz do sistema .
6 % b - lado direito do sistema .
7 % x - aproximacao inicial .
8 % TOL - tolerancia desejada .
9 % kmax - numero maximo de iteracoes .
10 % SAIDA :
11 % x - aproximacao final encontrada .
12 % k - numero de iteracoes realizadas .
13 function [x , k ] = metGSMat (A ,b ,x , TOL , kmax )
14
15 k = 0;
16 F = tril ( A ) ;
17 U = A - F ;
18 while norm (b - A * x ) > TOL && k <= kmax
19 x = F \( - U * x + b ) ;
20 k = k + 1;
21 end
critério de parada em relação que a forma matricial do Jacobi. Isso decorre da necessidade
de, a cada iteração termos que resolver um sistema linear no método de Gauss-Seidel.
Vimos que o critério das linhas define uma condição suficiente para convergência,
porém ela não é necessária. Na prática, o que determina a velocidade com a qual o método
irá convergir são os autovalores das matrizes −D−1 (L + U ) e (L + D)−1 .
3.4. Exercícios 79
3.4 Exercícios
1. Faça três iterações do método de Jacobi para os sistemas lineares abaixo. Utilize
x0 = [0 0 0]T .
3x1 − x2 + x3 = 1
a) 3x1 + 6x2 + 2x3 = 0
3x1 + 3x2 + 7x3 = 4
4x1 + x2 − x3 = 5
b) −x1 + 3x2 + x3 = −4
2x1 + 2x2 + 5x3 = 1
10x1 − x2 = 9
c) −x1 + 10x2 − 2x3 = 7
−2x2 + 10x3 = 6
4x1 + x2 + x3 = 5
d) −2x1 + 5x2 + x3 = 0
3x1 + x2 + 6x3 = −6.5
OBS: Note que a matriz desta questão não é diagonal dominante e nem pode ser
transformada em uma através de trocas de linhas e colunas.
7. Implemente uma function que retorna uma variável booleana (verdadeiro 1 ou falso
0) analisando se uma matriz é diagonal dominante ou não.
0.3x − 0.3x2 = 0.
1
81
4 Interpolação
Definição 4.1 Interpolar uma função f consiste em aproximá-la por uma outra fun-
ção, g, escolhida entre uma classe de funções definidas a priori e que satisfaça algumas
propriedades.
• quando conhecemos somente alguns dos valores numéricos da função (dados obtidos
experimentalmente, por exemplo) e é necessário estimar o valor da função em um
ponto não tabelado ou fazer alguma projeção;
• quando a função em estudo tem uma expressão tal que operações como a diferenciação
e a integração são difíceis, impossíveis ou inviáveis de serem realizadas.
Neste capítulo trataremos do problema encontrar um polinômio pn (x) que passa por
um conjunto de pontos (x0 , f (x0 )), (x1 , f (x1 )), . . . , (xn , f (xn )) da função f . O polinômio pn
é chamado de polinômio interpolador e os pontos são chamados de pontos de interpolação.
“Dado o conjunto de n + 1 pontos distintos (x0 , f (x0 )), (x1 , f (x1 )),
. . . , (xn , f (xn )), aproximar f (x) por um polinômio y = pn (x), de grau
menor ou igual a n tal que
f (xi ) = pn (xi )
para i = 0, 1, 2, . . . , n.”
Teorema 4.1 Dada a função f (x) e o conjunto de n + 1 pontos distintos (x0 , f (x0 )),
(x1 , f (x1 )), . . . , (xn , f (xn )), existe um único polinômio pn (x), de grau menor ou igual
a n tal que f (xi ) = pn (xi ) para i = 0, 1, 2, . . . , n.
Demonstração: Seja
pn (x) = a0 + a1 x + a2 x2 + . . . + an xn
um polinômio qualquer de grau menor ou igual a n. Para que pn (x) seja o interpolador
do conjunto de pontos precisamos obter os seus coeficientes a0 , a1 , a2 , . . . , an de modo que
f (xi ) = pn (xi ), para i = 0, 1, . . ., n. Assim,
f (x0 ) = pn (x0 ) = a0 + a1 x0 + a2 x0 2 + . . . + an x0 n
f (x1 ) = pn (x1 ) = a0 + a1 x1 + a2 x1 2 + . . . + an x1 n
..
.
f (xn ) = pn (xn ) = a0 + a1 xn + a2 xn 2 + . . . + an xn n
x −1 0 2
f (x) 4 1 −1
Solução: Como temos 3 pontos, o polinômio interpolador terá grau menor ou igual
a 2. O sistema tem a forma:
a0 + a1 x0 + a2 x0 2 = f (x0 )
a0 + a1 x1 + a2 x1 2 = f (x1 )
a0 + a1 x2 + a2 x2 2 = f (x2 )
Observação 4.2 Tome o cuidado para não confundir a forma de Newton que iremos
estudar com o método de Newton para zero de funções que vimos no capítulo 2.
polinômios de grau menor ou igual a 2, isto é, todo polinômio de grau menor ou igual a 2
pode ser escrito como combinação linear destes 3 polinômios.
k=0
Além disso, usando a segunda e terceira propriedade teremos que, para cada ponto
xi , o polinômio pn (x) produzido irá interpolar os dados:
O que nos resta agora é encontrar quem são estes polinômios Lk . Começamos
observando que, pela terceira propriedade, sabemos todas as raízes dos polinômios Lk .
Estas raízes são exatamente os pontos xi para i ∈ {1, . . . , n} ∩ {k}, isto é, todos os pontos
de interpolação exceto aquele com mesmo índice que o polinômio.
• x1 , x2 e x3 raízes de L0 (x);
• x0 , x2 e x3 raízes de L1 (x);
• x0 , x1 e x3 raízes de L2 (x);
• x0 , x1 e x2 raízes de L3 (x).
E não temos nenhuma outra raiz possível pois, segundo a primeira propriedade, os
polinômios tem grau n.
Portanto, sabemos que cada um dos polinômios Lk pode ser escrito na forma2 :
em que a é alguma constante. Note que os polinômios da forma acima satisfazem duas das
três propriedades.
Para que este polinômios satisfaçam a segunda propriedade devemos ter, para cada
k:
1
⇒a = .
(xk − x0 )(xk − x1 ) · · · (xk − xk−1 )(xk − xk+1 ) · · · (xk − xn )
Como os valores de xi são distintos entre si a está bem definido, isto é, não ocorrerá 0 no
denominador.
2
Lembre-se que quando temos uma equação do segundo grau ax2 + bx + c = 0 ela pode ser escrita na
forma a(x − r1 )(x − r2 ), em que r1 e r2 são as suas raízes.
88 Capítulo 4. Interpolação
ou ainda,
n
(x − xj )
Lk (x) =
Y
.
j=0 (xk − xj )
j6=k
Observação 4.3 Caso você não esteja familiarizado, a “letra π grande” na expressão
acima denota um produtório. Estes produtórios são semelhantes aos somatórios, porém ao
invés de somar cada termo, iremos multiplicá-los.
Exemplo 4.2 Problema: Considere os pontos de uma função f (x) tabelados abaixo:
xi 0 0, 5 1
f (xi ) 1, 3 2, 5 0, 9
(x − x1 )(x − x2 ) (x − 0, 5)(x − 1)
L0 (x) = = = 2x2 − 3x + 1
(x0 − x1 )(x0 − x2 ) (0 − 0, 5)(0 − 1)
(x − x0 )(x − x2 ) (x − 0)(x − 1)
L1 (x) = = = −4x2 + 4x
(x1 − x0 )(x1 − x2 ) (0, 5 − 0)(0, 5 − 1)
(x − x0 )(x − x1 ) (x − 0)(x − 0, 5)
L2 (x) = = = 2x2 − x
(x2 − x0 )(x2 − x1 ) (1 − 0)(1 − 0, 5)
= −5, 6x2 + 5, 2x + 1, 3.
Resta ainda aproximar o valor de f (0, 8). Para isso basta avaliar o polinômio neste
ponto e obteremos f (0, 8) ≈ p2 (0, 8) = 1, 876.
4.1.1 Implementação
Antes de mais nada, precisamos perceber que, diferente dos métodos vistos nos
capítulos 2 e 3, a interpolação não é um processo iterativo e, portanto, não necessitamos
de um critério de parada.
Como no somatório em (4.1) vai de 0 até n temos que adaptá-lo para os índices do
vetor X. Portanto, o for utilizado no somatório irá de 1 até m.
90 Capítulo 4. Interpolação
O somatório, a partir do momento que temos Lk , segue a ideia padrão (veja 8.22):
p = 0;
para k = 1 até m
p = p + Yk · L;
fim
m = length(X);
p = 0;
para k = 1 até m
L = 1;
para j = 1 até m
se j 6= k
L = L · (x − Xj )/(Xk − Xj );
fim
fim
p = p + yk · L;
fim
Algoritmo 5: Forma de Lagrange para interpolação.
Para implementar esta function usaremos como variáveis de entra dois vetores X e
Y com as coordenadas dos pontos que iremos interpolar. Como variável de saída temos
apenas o vetor p com o polinômio interpolador. A variável simbólica será x e vai ser
declarada dentro da function. O código finalizado é dado abaixo.
4.2. Forma de Newton 91
Definição 4.2 Definimos a diferença dividida de ordem zero de uma função f (x) definida
92 Capítulo 4. Interpolação
f [xi ] = f (xi ).
Definimos a diferença dividida de ordem n de uma função f (x) definida nos pontos
xi , i = 0, 1, . . ., n por:
..
.
f [x1 , x2 ] − f [x0 , x1 ]
f [x0 , x1 , x2 ] =
(x2 − x0 )
f [x2 , x3 ] − f [x1 , x2 ]
f [x1 , x2 , x3 ] =
(x3 − x1 )
..
.
Exemplo 4.3 Problema: Considere os pontos de uma função f (x) tabelados abaixo:
xi −1 0 1 2 3
f (xi ) 1 1 0 −1 −2
f [x3 ] − f [x2 ] −1 − 0
f [x2 , x3 ] = = = −1
(x3 − x2 ) 2−1
Atualizamos a tabela:
f [x1 , x2 ] − f [x0 , x1 ] −1 − 0 1
f [x0 , x1 , x2 ] = = =−
(x2 − x0 ) 1 − (−1) 2
Atualizamos a tabela:
Atualizamos a tabela:
4.2. Forma de Newton 95
Observação 4.4 Reveja o exemplo acima tentando identificar as posições nas quais os
valores que serão usados para calcular uma diferença dividida se encontram. Isso ajudará
a construir o pseudocódigo desta parte.
Observação 4.5 Uma propriedade interessante das diferenças divididas e que garante
a coerência na construção da forma de Newton é que podemos permutar x0 , x1 , . . . , xn
como quisermos e as diferenças divididas serão iguais. De fato, podemos visualizar isso
calculando:
f [x0 ] − f [x1 ] f [x1 ] − f [x0 ]
f [x1 , x0 ] = = = f [x0 , x1 ].
x0 − x1 x1 − x0
Para a ordem 2 temos a igualdade entre qualquer uma das 6 permutações:
Vamos agora construir a forma de Newton para interpolação. Seja f (x) uma função
contínua (n+1) vezes diferenciável no intervalo [a, b]. Sejam x0 , x1 , . . . , xn um conjunto
de (n + 1) pontos de [a, b].
Começamos por tomar apenas o ponto (x0 , f (x0 )) e calcular o polinômio interpolador
p0 (x), que na verdade não passa de uma função constante igual a f (x0 ). Agora, note que
para qualquer ponto x 6= x0 temos:
f [x] − f [x0 ] f (x) − f (x0 )
f [x0 , x] = =
(x − x0 ) (x − x0 )
Passamos agora a usar dois pontos: (x0 , f (x0 )) e (x1 , f (x1 )). O polinômio inter-
polador agora tem ordem 1, ou seja, uma reta. Para um ponto x diferente de x0 e x1
temos:
f [x1 , x] − f [x0 , x1 ]
f (x)−f (x1 )
(x−x1 )
− f [x0 , x1 ]
f [x0 , x1 , x] = = =
(x − x0 ) (x − x0 )
f (x)−f (x0 )
(x−x0 )
− (x−x1 )
(x−x1 )
f [x0 , x1 ] f (x)−f (x0 )−(x−x1 )f [x0 ,x1 ]
(x−x1 )
= = =
(x − x0 ) (x − x0 )
f (x1 ) − f (x0 )
p1 (x1 ) = f (x0 ) + (x1 − x0 )f [x0 , x1 ] = f (x0 ) + (x1 − x0 ) =
x1 − x0
Assim como ocorreu para 1 ponto, conseguimos expressar f (x) como a soma do
polinômio interpolador p1 (x) e o erro E1 (x).
Este procedimento pode ser prosseguido para qualquer quantia de pontos desejada.
De modo geral, a forma de Newton para o polinômio interpolador de grau ≤ n que
interpola f (x) em x0 , x1 , . . . , xn é:
x −1 0 2
f (x) 4 1 −1
7 2
= 1 − x + x2 .
3 3
Observação 4.6 No exemplo acima usamos frações para encontrar o polinômio na forma
exata, mas usar o formato decimal é correto também e geralmente mais viável.
4.2.1 Implementação
Olhando para o exemplo 4.3 vemos que, conforme deslocamos para a direita na
tabela, o número de linhas ocupadas diminui uma unidade (os demais espaços receberão 0).
Isso indica que, para cada coluna j, iremos percorrer da primeira linha até a linha “alguma
coisa menos j”. Se denotarmos por imax o limite superior o qual a linha irá percorrer
notamos o seguinte:
4.2. Forma de Newton 99
j 1 2 3 4 5
imax m m−1 m−2 m−3 m−4
Analisando a relação dos índice na tabela acima vemos que imax == m+1-j. Por-
tanto, dentro do loop que percorre as colunas, fazemos um loop que percorre da linha 1
até m+1-j. O esboço (ainda falta uma parte) do algoritmo fica:
para j = 2 até m
para i = 1 até m + 1 − j
Tij =???
fim
fim
Ainda olhando para o exemplo 4.3, vamos tentar intuir os índices envolvido na
conta de (4.3). Primeiramente, note que no numerador sempre utilizamos os elementos da
coluna anterior (j-1) e das linhas i e i+1. Ou seja, o numerador pode ser escrito como
Ti+1,j−1 − Ti,j−1
Tij = , j ∈ {2, . . . , m}, i ∈ {1, . . . , m + 1 − j}.
???
j 2 2 2 2 3 3 3 4 4 5
i 1 2 3 4 1 2 3 1 2 1
Índice do vetor 2 3 4 5 3 4 5 4 5 5
Com um pouco de atenção você perceberá que o índice do vetor consiste em i+j-1
em todos os casos. Portanto, a expressão dos índices da matriz de diferenças divididas fica:
Ti+1,j−1 − Ti,j−1
Tij = .
Xi+j−1 − Xi
para j = 2 até m
para i = 1 até m + 1 − j
Tij = (Ti+1,j−1 − Ti,j−1 )/(Xi+j−1 − Xi );
fim
fim
1o termo: 1
2o termo: (x − x0 )
3o termo: (x − x0 )(x − x1 )
.. ..
. .
A forma eficiente de fazer esta parte consiste em usar uma variável para denotar o
polinômio que está sendo utilizado e, a cada repetição, multiplicá-lo pelo termo adicional.
4.2. Forma de Newton 101
Junto a esse algoritmo precisamos incluir a somatória dos termos de (4.4). Essa
soma consiste essencialmente em, para cada j, multiplicar polin pela diferença dividida
correspondente. Esta trecho pode ser mais complicado de interpretar e visualizar que os
índices estão corretos:
p = T (1, 1);
polin = 1;
para j = 2 até m
polin = polin · (x − Xj−1 );
p = p + polin ∗ T (1, j);
fim
13 m = length ( X ) ;
14 T = zeros ( m ) ;
15 T (: ,1) = Y ;
16 for j = 2: m
17 for i = 1:( m +1 - j )
18 T (i , j ) = ( T ( i +1 ,j -1) - T (i ,j -1) ) /( X ( i +j -1) - X ( i ) ) ;
19 end
20 end
21
22 p = T (1 ,1) ;
23 produto = 1;
24 for j = 2: m
25 produto = produto *( x - X (j -1) ) ;
26 p = p + produto * T (1 , j ) ;
27 end
Definição 4.3 Definimos a diferença finita de ordem zero de uma função f (x) no ponto
xi por:
∆0 f (xi ) = f (xi )
Exemplo 4.5 Problema: Considere os pontos de uma função f (x) tabelados abaixo:
xi 0, 5 0, 7 0, 9 1, 1
f (xi ) 5, 8 7, 9 10, 1 12, 3
Teorema 4.2 Seja f (x) uma função contínua e (n + 1) vezes diferenciável no intervalo
[a, b]. Sejam x0 , x1 , . . . , xn (n + 1) pontos distintos e equidistantes deste intervalo. Então
∆n f (x0 )
f [x0 , x1 , . . . , xn ] = .
hn n!
∆f (x0 ) ∆2 f (x0 )
pn (x) = ∆0 f (x0 ) + (x − x0 ) + (x − x0 )(x − x1 ) +
h 2!h2
∆n f (x0 )
+ . . . + (x − x0 )(x − x1 ) . . . (x − xn−1 ) . (4.6)
n!hn
Exemplo 4.6 Problema: Considere os pontos de uma função f (x) tabelados abaixo:
xi 0 0, 1 0, 2
f (xi ) 1 1
2
2
3
4.3. Forma de Newton-Gregory 105
Solução: O primeiro passo é verificar que podemos aplicar esta forma. Como os
xi são espaçados igualmente por h = 0, 1 estamos dentro da condição necessária.
∆f (x0 ) ∆2 f (x0 )
p2 (x) = ∆0 f (x0 ) + (x − x0 ) + (x − x0 )(x − x1 ) =
h 2!h2
2/3
!
−1/2
=1+ x + x(x − 0, 1) =
0, 1 2(0, 1)2
25 100 2
=1− x+ x.
3 3
Observação 4.7 No exemplo acima usamos frações para encontrar o polinômio na forma
exata, mas usar o formato decimal é correto também e geralmente mais viável.
4.3.1 Implementação
para j = 2 até m
para i = 1 até m + 1 − j
Tij = Ti+1,j−1 − Ti,j−1 ;
fim
fim
Por fim, a parte que constrói o polinômio precisa apenas das adequações:
p = T (1, 1);
polin = 1;
para j = 2 até m
polin = polin ∗ (x − X(j − 1));
p = p + polin ∗ T (1, j)/(hj−1 ∗ (j − 1)!);
fim
17 for i = 1:( m +1 - j )
18 T (i , j ) = T ( i +1 ,j -1) - T (i ,j -1) ;
19 end
20 end
21
22 h = X (2) - X (1) ;
23 p = T (1 ,1) ;
24 produto = 1;
25 for j = 2: m
26 produto = produto *( x - X (j -1) ) ;
27 p = p + produto * T (1 , j ) /( h ^( j -1) * factorial (j -1) ) ;
28 end
AVISO: Note que nesta implementação não estamos verificando se os pontos fornecidos
são igualmente espaçados. Você pode implementar este teste se desejar.
Lagrange n2 + n − 1 n2 − 1 2n 2n2 + 3n − 2
n2 −n 3n2 + 5n − 10
Newton n2 + n − 2 2n − 3 2
2
n2 + 3n − 4 n + 9n − 12
2
Newton-Gregory 2n − 3 n−1
2 2
Para interpretar estes valores, olhamos para a coluna de totais e apenas para o
termo de ordem mais alta (n2 nas três formas). A forma de Newton faz cerca de 25%
menos operações que a forma de Lagrange. Já a forma de Newton-Gregory precisa de
108 Capítulo 4. Interpolação
cerca de 33% menos operações que a forma de Newton precisaria e 75% a menos que a de
Lagrange.
Já a forma de Newton é uma boa alternativa quando os pontos não forem igualmente
espaçados e não caímos na situação na qual a forma de Lagrange tira proveito. Além
disso, a forma de Newton é adequada quando precisamos adicionar pontos após calcular
o interpolador. Por exemplo, se fizermos o interpolador na forma de Newton para um
conjunto de 3 pontos e depois recebermos um quarto ponto, podemos reaproveitar o
polinômio e a tabela de diferenças divididas já calculados.
Por fim, para fins de comparação, o sistema linear com a matriz de Vandermonde
apresentado na introdução do capítulo precisaria de aproximadamente 2n3 /3 operações.
4.5. Exercícios 109
4.5 Exercícios
2. Calcule o polinômio interpolador dos exemplos do texto com os demais métodos que
não foram aplicados (quando possível, no caso da forma de Newton-Gregory).
xi 0 1 2 3
f (xi ) 0.0 0.8415 0.9093 0.1411
5. Considere os dados do exercício anterior com a adição do ponto (4, 0.53). Refaça os
itens a e b e indique aquele que foi menos trabalhoso e justifique.
7. Seja f uma função dada por um polinômio de grau 3. Explique por que a interpolação
de um conjunto de 4 ou mais pontos distintos extraídos desta função irá resultar em
um interpolador igual a f .
t, o C cp , kcal/(kg o C)
200 1.075
220 1.102
240 1.136
260 1.183
280 1.250
x 0 1 2 3
f1 (x) 0.031833 0.27692 0.046171 0.097132
f2 (x) 0.82346 0.69483 0.3171 0.95022
11. Escreva um script que define um conjunto de pontos (escolha um dos exercícios
acima) e aplica os três métodos estudados. Ao final, o código deve verificar que os
três são iguais.
13. Edite as implementações dos 3 métodos apresentadas neste capítulo para que elas
exibam algumas das informações importantes para auxiliá-lo nos exercícios de conta.
Por exemplo, na forma de Newton faça o código exibir na Janela de comandos a
tabela de diferenças divididas.
14. Crie um script para plotar o gráfico do interpolador (escolha os dados de um dos
exercícios acima). Lembre-se que, se você plotar apenas os pontos de interpolação
você obterá um gráfico que não se assemelha a um polinômio. Portanto, é importante
avaliar o interpolador em mais pontos. Para isso, você pode fazer:
Pesquise o que a function linspace faz, entenda o trecho de código acima e use-o
no seu script.
15. Crie uma function que recebe possa ser usada para adicionar pontos a um polinômio
interpolador obtido pelo código 4.2. Crie um script que declara um conjunto de dados
(use dos exercícios acima); constrói o polinômio interpolador usando 4.2; declara
um novo ponto e chama a function criada para gerar o novo interpolador sem a
necessidade de repetir todas as contas feitas.
16. Implemente um script para testar o erro numérico da interpolação. Para isso, faça:
5 Ajuste de Curvas
No entanto, nem sempre este polinômio irá aproximar muito bem a função no
restantes dos pontos, veja a figura 11 em x = 0.05 e 0.95 por exemplo. Uma alternativa para
esta estratégia consiste em estudar o comportamento dos pontos (também conhecidos como
dados) de um ponto de vista mais global. Isto é, ao invés de garantir que a aproximação
passe exatamente sobre cada pontos, vamos procurar funções que descrevam os crescimentos
e decrescimentos dos dados sem necessariamente passar por eles.
Outro ponto que nos atrai a essa alternativa é a origem dos dados. Frequentemente
os dados sobre um função são obtidos de forma experimental ou através de medições
com equipamentos. Estas podem gerar erros de truncamento ou imprecisões nas medições.
Portanto, a ideia de encontrar uma curva que passa exatamente por esses pontos se torna
desnecessária.
“Dado o conjunto de n pontos distintos (x1 , f (x1 )), ..., (xn , f (xn )),
encontrar uma curva que melhor descreve (em algum sentido) estes
pontos.”
O problema descrito acima pode ser abordado de diversas formas e com vários
métodos (eles são muito estudados na estatística). Neste capítulo nos limitaremos a um
deles: o método dos mínimos quadrados.
y = ax + b. (5.1)
ỹi = axi + b, i = 1, . . . , n.
1
Este será o nosso modelo.
5.1. Método dos Mínimos Quadrados 115
Definimos o desvio do modelo como a soma dos quadrados dos desvios em cada ponto, isto
é:
n
d= d2i .
X
i=1
No caso que estamos construindo (isto é, quando o modelo é uma reta) o desvio
em xi é:
di = yi − ỹi = yi − axi − b
e o desvio do modelo é:
n n
d(a, b) = d2i = (yi − axi − b)2 .
X X
i=1 i=1
Observação 5.1 Como o desvio em cada ponto pode ser positivo ou negativo, precisamos
definir o desvio do modelo de modo que o desvio em um ponto não cancelasse o desvio
em outro ponto. Desta forma, o desvio do modelo é um função sempre positiva. Poderia
ter conseguido uma função positiva se tivéssemos utilizado a função módulo ao invés do
quadrado. Porém, precisaremos derivar a função d e o quadrado nos garante que o desvio
seja uma função diferenciável em todos os pontos.
É muito importante observar que o desvio do modelo é uma função cujas variáveis
independentes são os coeficientes do modelo e não os pontos (xi , yi ). Isso ocorre pois o
desvio do modelo varia para diferentes curvas e o que define essas curvas são os coeficientes.
Portanto, o que queremos encontrar são os coeficientes da curva (a e b no caso da reta) de
modo que o desvio do modelo seja o menor possível. Foi esta a noção de “melhor forma
possível” a qual nos referíamos no início desta seção.
Observação 5.2 No caso dos modelos lineares2 o desvio do modelo, além de ser uma
função positiva, é um paraboloide com a concavidade voltada para cima. Isso garante que
encontrar o seu mínimo é um objetivo alcançável.
2
Definiremos o conceito de modelo linear e não-linear na próxima seção.
116 Capítulo 5. Ajuste de Curvas
Assim, podemos dizer que sem peso na consciência que queremos encontrar o par
(a, b) que minimiza a função d(a, b). Da teoria do cálculo de funções de várias variáveis
sabemos3 que o mínimo da função d(a, b) ocorre quando ∇d(a, b) = 0.
Você pode observar que o sistema linear acima pode ser reescrito como
1 x1 y1
1 1 ··· 1 1 x2 1 1 ··· 1 y2
b
= . (5.3)
.. .. ..
x1 x2 · · · xn . . a x1 x2 · · · xn .
1 xn
yn
Se denotarmos
1 x1
1 x2
A=
. ..
.
. .
1 xn
⇒ AT Av = AT y. (5.4)
3
Dado que a função d é um paraboloide, os pontos críticos se resumem à apenas um único ponto.
5.2. Caso Geral 117
Podemos mostrar que este sistema tem sempre exatamente uma única solução, que
é dada por v = (AT A)−1 AT y. É possível encontrar na literatura expressões explícitas para
os coeficientes a e b obtidos a partir da solução deste sistema linear. Como o objetivo
deste texto não é apenas aplicar fórmulas para um único modelo específico não iremos
apresentá-las aqui. De fato, do ponto de vista numérico, ter em mãos estas expressões não
tem vantagem significativa no caso deste modelo4 .
Exemplo 5.1 Encontre a reta que melhor aproxima os dados da tabela abaixo usando o
mínimos quadrados.
xi 1 2 3 4 5 6 7 8 9 10
yi 1.3 3.5 4.2 5.0 7.0 8.8 10.1 12.5 13.0 15.6
Precisamos resolver o sistema (5.1). Para isso, podemos usar as expressões (5.2)
ou (5.3). Em ambos os casos precisaremos calcular quatro somatórios:
n n n n
xi = 55, x2i = 385, yi = 81, xi yi = 572.4.
X X X X
cuja solução é a = 1.538 e b = −0.36. Portanto, a reta que melhor ajusta os dados da
tabela é p(x) = 1.538x − 0.36. A figura 12 mostra o gráfico dos pontos e do modelo obtido.
4
Para qualquer quantidade de pontos, resolver o sistema linear (5.4) exigirá o mesmo número de
operações algébricas que aplicar a fórmula pronta.
118 Capítulo 5. Ajuste de Curvas
1. Definir o modelo;
Definição 5.2 Dizemos que um modelo linear se o sistema obtido no passo 4 for um
sistema linear. Caso contrário, dizemos que é um modelo não-linear.
Mais uma vez, apesar de termos uma exponencial na expressão do modelo, o modelo é
linear.
Exemplo 5.4 Considere o modelo y = aebx . Desta vez, ao chegar no passo 4 encontrare-
mos um sistema de equações na forma:
n n
yi ebxi ae2bxi = 0,
X X
−
i=1 i=1
n n
xi yi aebxi a2 xi e2bxi = 0.
X X
−
i=1 i=1
Este sistema de equações não pode ser expresso na forma “matriz × vetor = vetor” e,
portanto, é chamado de sistema não-linear. Logo, o modelo é não-linear.
Nossa tarefa se torna muito mais simples quando percebemos o padrão que ocorre
nos modelos lineares. É nesse ponto que a forma (5.3) ganha seu destaque.
120 Capítulo 5. Ajuste de Curvas
Quando o modelo utilizado era y = ax + b, o sistema linear era dados por (5.3):
1 x1 y1
1 1 ··· 1 1 x2 1 1 ··· 1 y2
b
= . (5.7)
.. .. ..
x1 x2 · · · xn . . a x1 x2 · · · xn .
1 xn
yn
Se olharmos para os dois exemplos de modelos lineares acima com mais atenção veremos
que os sistemas podem ser escritos como
1 x1 x21 y1
1 1 1 1 1 1
··· c ···
1 x2 x2
2 y2
x1 x2 · · · xn b
=
x1 x2 · · · xn , (5.8)
.. .. .. ..
. . . .
x21 x22 · · · x2n a
x21 x22 · · · x2n
1 xn xn
2
yn
para a parábola e
1 e
x1
y1
1 1 1 1 e b 1 1 ··· 1
x2
··· y2
.
.
=
.. x1 x2
..
(5.9)
x1 x2 xn xn
e e ··· e .
. a
e e ··· e .
1 exn
yn
Observação 5.4 O mesmo procedimento feito aqui pode ser generalizado para modelos
de várias variáveis. Por exemplo, podemos procurar os coeficientes do plano que melhor
5.3. Implementação 121
ajusta um conjunto de pontos no espaço. Dessa forma, o modelo pode ser escrito como
z = ax + by + c e o sistema é
1 x1 y1 z1
1 1 ... 1 1 1 1
c ...
1 x2 y2 z2
x1 x2 . . . xn = x1 x2 .
b . . . xn
.. .... ..
. . . .
y1 y2 . . . yn
a
y1 y2 . . . yn
1 xn y n
zn
5.3 Implementação
A implementação do método dos mínimos quadrados é relativamente simples
(comparada com os demais capítulos). Podemos fazê-la de diversas formas, mas aqui iremos
apresentar duas.
12 somay = 0;
13 somaxy = 0;
14 somax2 = 0;
15 for i = 1: n
16 somax = somax + x ( i ) ;
17 somay = somay + y ( i ) ;
18 somaxy = somaxy + x ( i ) * y ( i ) ;
19 somax2 = somax2 + x ( i ) ^2;
20 end
21
22 B = [ n somax ; somax somax2 ];
23 rhs = [ somay ; somaxy ];
24 coef = B \ rhs ;
A versão abaixo faz uso da function sum para calcular os somatórios de forma mais
eficiente5 .
Código 5.2 – Método dos mínimos quadrados - primeira forma (usando sum).
1 % DESCRICAO : Implementacao da segunda forma do metodo dos
minimos quadrados .
2 %
3 % ENTRDA :
4 % - x : vetor com as abscissa dos dados .
5 % - y : vetor com as ordenada dos dados .
6 % SAIDA :
7 % - coef : vetor com os coeficientes da reta .
8 function coef = mmq (x , y )
9
10 n = length ( x ) ;
11 somax = sum ( x ) ;
12 somay = sum ( y ) ;
13 somaxy = sum ( x .* y ) ;
5
Não apenas mais simples mas também mais rápida.
5.3. Implementação 123
1 A = [ ones (n ,1) x ];
Tendo a variável A definida, basta então resolver o sistema linear (5.4) usando a
barra “\”:
9
10 n = length ( x ) ;
11 A = [ ones (n ,1) x ];
12 coef = (A '* A ) \( A '* y ) ;
5.4 Exercícios
a) y = ax2 + bx + c;
b) y = a sen(x) + b cos(x);
c) y = ax2 + by 2 + cxy;
xi -2 -1 0 1 2
yi 6 2 -1 1 4
4. Crie functions, com base na implementação 5.3, para os modelos lineares dados na
questão 1.
5. Pesquise como é feita a leitura de arquivos de dados (do Excel, por exemplo) no
MATLAB. Escreva um script que lê um conjunto de dados de um arquivo, realiza
um ajuste e plota estas informações.
6. Considere os pontos da tabela a seguir. Encontre o ajuste pelo método dos quadrados
mínimos utilizando o modelo z = ax + by + c.
x 0 1 1 2
y 0 2 3 1
z 1 2 3 4
8. A tabela abaixo fornece o número de habitantes do Brasil (em milhões) desde 1872:
126 Capítulo 5. Ajuste de Curvas
x 1872 1890 1900 1920 1940 1950 1960 1970 1980 1991
y 9.9 14.3 17.4 30.6 41.2 51.9 70.2 93.1 119.0 146.2
9. Refaça a questão anterior usando6 x = [0, 18, 28, 48, 68, 78, 88, 98, 108,
119]'; e a mesma ordem polinomial. Compare os coeficientes encontrados, o gráfico
das curvas e as estimativas. Calcule também o número de condição das matrizes
quadradas do sistema linear usando o comando cond(A'*A).
OBS: O número de condição de uma matriz é uma medida que envolve os seus
autovalores e é sabido que quanto maior o seu valor mais suscetível a perturbações
numéricas e erros o sistema está (veja a seção 1.4). Muitas vezes, quando x contém
valores muito altos podemos obter coeficientes para os ajustes muito diferentes do
que obteríamos usando aritmética exata.
6
Este valores são exatamente iguais aos anos da tabela original, porém subtraído 1872.
127
6 Integração Numérica
Além disso, o Teorema fundamental do cálculo nos diz que a integral definida de
f (x) calculada no intervalo [a, b] é dada por
Z b
f (x) dx = F (b) − F (a).
a
Antes de apresentarmos os dois métodos vamos tratar um que deve ser familiar a
qualquer um que viu a construção da integral de Riemann num curso de cálculo como o
limite das somas de Riemann (veja a figura 13).
de grau 0 (constante). Com isso, podemos contextualizar a soma de Riemann como a soma
da integral de cada interpolador de grau 0 que aproxima a função nos subintervalos.
(x − x1 ) (x − x0 )
p1 (x) = f (x0 ) + f (x1 ) =
(x0 − x1 ) (x1 − x0 )
(x − x1 ) (x − x0 )
= f (x0 ) + f (x1 ) .
−h h
Z x1 "
(x − x1 ) (x − x0 )
#
= f (x0 ) + f (x1 ) dx
x0 −h h
= Área do Trapézio
h
= [f (x0 ) + f (x1 )]
2
Exemplo 6.1 Problema: Calcule o valor aproximado de 0,5 (ln x + x)dx usando a Regra
R1
dos Trapézios.
h
= [f (x0 ) + 2f (x1 ) + 2f (x2 ) + · · · + 2f (xn−1 ) + f (xn )] (6.2)
2
Note que, como f (xi ), para i = 1, . . . , n − 1, aparece duas vezes (uma à esquerda e
outra à direita) então os termos intermediários da expressão acima aparecem multiplicados
por 2 enquanto as extremidades por 1. Quando fazemos a conta da expressão (6.2), ou
implementamos ela, podemos usar qualquer uma das duas formas.
R4√
Exemplo 6.2 Problema: Calcule o valor aproximado de 1 x dx usando a regra dos
Trapézios Generalizada para 6 subintervalos.
b−a 4−1 1
h= = = .
n 6 2
√
Como o integrando f (x) = x possui primitiva podemos calcular o valor da integral
exata para compararmos. O valor obtido é 4.6667.
6.1.1 Implementação
Aqui iremos optar por fazer da segunda forma. Deixamos assim a tarefa de definir os
pontos e avaliar a função para o script.
Uma primeira forma de implementar a regra dos trapézios generalizada pode ser
escrevendo (6.2) como o somatório:
Z xn
h h h n−1
f (x)dx ≈ [f (x0 ) + f (x1 )] + . . . + [f (xn−1 ) + f (xn )] = (f (xi ) + f (xi+1 ))
X
x0 2 2 2 i=0
1 I = 0;
2 for i = 1: m -1
3 I = I + ( y ( i ) + y ( i +1) ) ;
4 end
5 I = I * h /2;
Note que mudamos o índice i para ir de 1 até m − 1. Isso ocorre por causa da
diferença no início da indexação no código e na expressão matemática e que precisa ser
compensada. O código abaixo é a versão completa desta primeira forma.
16 for i = 1: m -1
17 I = I + ( y ( i ) + y ( i +1) ) ;
18 end
19 I = I * h /2;
Neste caso, o somatório precisa ser feito apenas dos termos intermediários. Podemos
optar por começar a soma já com a soma das extremidades, mas teríamos que multiplicar
por h dentro do for para a conta estar correta. A outra forma seria começar em I = 0,
multiplicar por h no final e somar o termo das extremidades depois. Estas duas formas
estão apresentadas abaixo.
16 for i = 2: m -1
17 I = I + h*y(i);
18 end
Uma quarta forma de fazer esta implementação de forma mais inocente seria olhar
a expressão:
Z xn
h
f (x)dx ≈ [f (x0 ) + 2f (x1 ) + 2f (x2 ) + · · · + 2f (xn−1 ) + f (xn )]
x0 2
da forma como ela é apresentada. Com isso precisaríamos um if para distinguir o coeficiente
que multiplica os valores de f (xi ). O código abaixo implementa esta forma, porém é possível
6.1. Regra dos Trapézios 135
Por fim, podemos fazer a conta deste método vetorizadamente. Para isso, usamos a
function sum para somar os termos intermediários ao invés de um loop for. Veja abaixo
como esta forma fica.
136 Capítulo 6. Integração Numérica
O script a seguir apresenta de forma bem simplificada que todas as formas apre-
sentadas coincidem.
O primeiro ponto que precisamos tomar cuidado neste caso é que necessitamos de
3 pontos para produzir um polinômio interpolador de grau menor ou igual a 2. Sendo
assim, vamos usar o ponto médio do intervalo de integração para produzir o polinômio
interpolador.
Z b Z x2
f (x0 ) Z x2
f (x) dx ≈ p2 (x) dx = (x − x1 )(x − x2 ) dx−
a x0 2h2 x0
f (x1 ) Z x2
− (x − x0 )(x − x2 ) dx+
h2 x0
f (x2 ) Z x2
+ (x − x0 )(x − x1 ) dx.
2h2 x0
138 Capítulo 6. Integração Numérica
Infelizmente, calcular estas integrais não é tão simples quanto foi no caso da regra
do trapézio. Para resolvê-las de forma genérica e obter uma forma simplificada vamos
aplicar uma mudança de variáveis que irá remover os pontos xi do integrando.
dx
x − x0 = zh ⇒ x = x0 + zh ⇒ = h ⇒ dx = hdz.
dz
x − x0 = zh,
x = x0 ⇒ x0 − x0 = zh ⇒ z = 0,
x = x1 ⇒ x1 − x0 = zh ⇒ z = 1,
x = x2 ⇒ x2 − x0 = zh ⇒ z = 2.
6.2. Regra 1/3 de Simpson 139
f (x0 )h Z 2
= (z − 1)(z − 2)dz
2 0
f (x1 ) Z x2 f (x1 ) Z 2
(x − x0 )(x − x2 )dx = zh(z − 2)hhdz
h2 x0 h2 0
Z 2
= f (x1 )h z(z − 2)dz
0
f (x2 ) Z x2 f (x2 ) Z 2
(x − x 0 )(x − x 1 )dx = zh(z − 1)hhdz
2h2 x0 2h2 0
f (x2 )h Z 2
= z(z − 1)dz
2 0
f (x2 )h Z 2 f (x2 h) 2 1
z(z − 1)dz = = f (x2 )h
2 0 2 3 3
Somando estes três termos (lembrando que o segundo precisa trocar de sinal)
encontramos a regra de Simpson 1/3 simples2 :
Z b
h
f (x) dx ≈ [f (x0 ) + 4f (x1 ) + f (x2 )]. (6.3)
a 3
Z 1,5
Exemplo 6.3 Problema: Calcule o valor aproximado da integral cos x dx usando
0,5
a regra do 1/3 de Simpson.
xi 0, 5 1, 0 1, 5
f (xi ) 0, 8776 0, 5403 0, 0707
0, 5
= (0, 8776 + 4 × 0, 5403 + 0, 0707) = 0, 5183.
3
Z 3
Exemplo 6.4 Problema: Calcule o valor aproximado de xex + 1 dx usando a regra
0
de 1/3 de Simpson para 6 subintervalos.
Z 3
h
(xex + 1) dx ≈ [f (x0 ) + 4f (x1 ) + 2f (x2 ) + 4f (x3 ) + 2f (x4 ) + 4f (x5 ) + f (x6 )] =
0 3
0.5
= (1.0000 + 4 × 1.8244 + 2 × 3.7183 + 4 × 7.7225 + 2 × 15.7781+
3
Mais do que isso, é possível mostrar que o erro na regra de Simspon 1/3 decai
muito mais rápido que o erro na regra dos trapézios quando n aumenta.
142 Capítulo 6. Integração Numérica
6.2.1 Implementação
Assim como na regra dos trapézios, existem diversas formas de implementar (6.4).
Primeiramente precisamos notar que precisaremos levar em conta que os coeficientes dos
termos intermediários alternam de valor.
Neste caso usamos a function mod para distinguir entre os índices pares e ímpares.
É interessante perceber que em (6.4) os índices (intermediários) pares são multiplicados
por 2 e os ímpares por 4. Porém, no código isso é invertido pois começamos a numeração
por 1 e não por 0.
Outra forma interessante de seguir nessa mesma ideia é usando uma variável c
que muda de valores a cada repetição do for. Para isso, podemos trocar o for do código
acima pelo trecho abaixo.
1 c = 4;
2 for i = 2: m -1
3 I = I + c*y(i);
4 if c == 4
5 c = 2;
6 else
7 c = 4;
8 end
9 end
6 % SAIDA :
7 % I - Aprox da integral .
8 function I = regraSimp2 (x , y )
9
10 % n = numero de subintervalos .
11 m = length ( x ) ; % Numero de pontos .
12 % m = n +1;
13 h = x (2) - x (1) ;
14
15 I = y (1) + y ( m ) ;
16 for i = 2:2: m -1
17 I = I + 4* y ( i ) ;
18 end
19 for i = 3:2: m -1
20 I = I + 2* y ( i ) ;
21 end
22 I = I * h /3;
Poderíamos ter feito o código mais parecido com a expressão que escrevemos se
fizermos da forma a seguir (lembre-se que m == n+1).
A quarta forma que podemos fazer este código é pensar nos termos intermediários
como pares 4 − 2. Porém, devemos tomar o cuidados que um termo multiplicado por 4 irá
sobrar3 . Assim, a conta poderia ser feita como no trecho abaixo.
1 I = y (1) + y ( m ) ;
2 for i = 2:2: m -2
3 I = I + 4* y ( i ) + 2* y ( i +1) ;
4 end
5 I = ( I + 4* y (m -1) ) * h /3;
Neste caso, temos apenas um somatório com passo 2. O código fica como abaixo.
12 % m = n +1;
13 h = x (2) - x (1) ;
14
15 I = ( h /3) *( y (1) + y ( m ) + 4* sum ( y (2:2: m -1) ) + 2* sum ( y (3:2: m
-1) ) ) ;
O script a seguir apresenta de forma bem simplificada que todas as formas apre-
sentadas coincidem.
6.3 Exercícios
a) b) c) d) e) f)
Exata 2.667 6.400 1.099 2.958 1.416 6.389
Resposta:
Trapézios 4.000 16.000 1.333 3.326 0.909 8.389
Simpson 2.667 6.667 1.111 2.964 1.425 6.421
6. Escreva um script para verificar a resposta das questões que você fez em papel.
8. Uma das formas mais comuns de se medir o erro na aproximação de uma função por
outra (como no caso de interpolação ou ajuste de curvas) é através da expressão,
conhecida como erro L2 ,
Z b
kf − gk = (f (x) − g(x))2 dx.
a
√
Se f (x) = 1 + x2 e g é o polinômio interpolador de f de grau 2 no intervalo
[0, 2] (use o método de interpolação de sua preferência). Use a regra de Simpson
generalizada, com n = 8 subintervalos, para aproximar o valor do erro L2 causado
pelo interpolador. Implemente um código que faz essa conta. OBS: Neste caso o
integrando será (f (x) − g(x))2 .
9. Proponha e implemente uma estratégia para aproximar o valor de uma integral dupla
sobre um domínio quadrado, isto é:
Z dZ b
f (x, y)dxdy
c a
Escolha uma função cujo valor da integral seja conhecido para testar seu código.
SUGESTÃO: Para cada valor de y fixo, a integral dupla pode ser aproximada por
uma integral simples.
10. Um automóvel percorre uma distância entre duas cidades em 10 horas. Com auxílio
de um marcador, temos a velocidade do automóvel a cada hora, conforme dados a
seguir:
Tempo (horas) 0 1 2 3 4 5
Vel. (km/h) 0 50.4 53.7 67.5 74.3 84.6
Tempo (horas) 6 7 8 9 10
Vel. (km/h) 92.1 98.3 100 105 110
Apesar da sua grande importância, nem sempre resolver analiticamente uma EDO
é uma tarefa fácil ou mesmo necessária. Muitas vezes, conhecer apenas uma solução
aproxima para a EDO é suficiente para obter as informações e fazer as análises necessárias.
É importante destacar que, apesar de (7.1) ser uma EDO de primeira ordem na
verdade os métodos apresentados aqui podem ser aplicados para equações de ordem mais
alta se os transformarmos em um sistema de EDOs de primeira ordem.
Definição 7.1 Se, para calcular yj usamos apenas yj−1 teremos um método de passo simples
ou passo um. Se usarmos mais valores, yj−1 , yj−2 , . . . , teremos um método de passo múltiplo.
Os três métodos que veremos são de passo simples. O método de passo múltiplo
mais conhecido chama-se Adams-Bashforth-Moulton ou preditor-corretor.
Considerando a solução y(x) do PVI (7.1), e assumindo que ela seja infinitamente
diferenciável, podemos escrever a sua série de Taylor:
∞
y (n) (x0 ) n
y(x0 + h) = h = y(x0 ) + y 0 (x0 )h + . . .
X
n=0 n!
Notação 7.1 Denotamos por y(xi ) o valor da solução exata do problema no ponto xi e
por yi o valor aproximado da solução, isto é, y(xi ) ≈ yi .
Outra forma de chegar nesta expressão seria usando a equação da reta tangente.
De fato, dado o ponto (x0 , y(x0 )) sobre o gráfico da solução exata do PVI (7.1), podemos
escrever a equação da reta:
y − y(x0 ) = m(x − x0 ),
em que (x, y) é qualquer ponto sobre a reta (não sobre o gráfico da solução) e m é a
declividade desta reta tangente. Como sabemos do cálculo de funções de uma variável
real a declividade desta reta é justamente o valor da derivada da função avaliada naquele
ponto: m = y 0 (x0 ). Já que a EDO (7.1) diz que y 0 = f (x, y) para todo x, então y 0 (x0 ) =
f (x0 , y(x0 )) = f (x0 , y0 ).
y1 − y0 = f (x0 , y0 )(x1 − x0 ),
⇒y1 = y0 + hf (x0 , y0 ).
em que (x1 , y1 ) é um ponto sobre a reta, mas que aproxima o valor da solução. Com isso,
basta repetir o processo e obter a expressão (7.2).
y(1, 2) ≈ y1 = y0 + h f (x0 , y0 ) = 3 + 0, 2 × (2 × 1 × 3) = 4, 2.
154 Capítulo 7. Equações Diferenciais Ordinárias
Note que, para calcular y1 não usamos o valor de x1 . Isso é um erro comum na
aplicação da expressão do método.
A solução exata deste PVI é y(x) = 3ex . A tabela e a figura abaixo resumem os
2 −1
resultados obtidos:
7.1.1 Implementação
Como você pode ter percebido a esta altura, o método de Euler consiste em, tendo
a primeira componente, percorrer da segunda até a última componente de um vetor y
preenchendo-o com os valores obtido a partir da expressão (7.2).
7.1. Método de Euler 155
Para fazer isso, utilizamos um for indo de 2 até n (número de pontos) ou de 1 até
n-1. Este trecho (que é praticamente o código inteiro) fica:
1 for i = 1: n
2 y ( i +1) = y ( i ) + h * f ( x ( i ) ,y ( i ) ) ;
3 end
É claro que precisamos de algumas coisas antes deste loop. Primeiro, vamos definir
as variáveis de entrada e saída da function. Para a saída colocamos os vetores x e y com as
aproximações encontrada. Como variável de entrada precisamos da função f definida como
anônima ou como inline para que possamos utilizar na forma como acima, do ponto inicial
que vamos chamar de x0, do ponto final xn até onde desejamos calcular a aproximação, o
número de passos n necessários para ir de x0 até xn e a condição inicial y0.
Observação 7.1 Assim como fizemos para as integrais numéricas no capítulo anterior,
vamos optar por ter n como variável de entrada ao invés de h para não ocorrer o caso em
que não conseguimos ir de x0 até xn com passos h.
3 % ENTRADA :
4 % f - funcao lado direito da EDO .
5 % x0 - ponto inicial do dominio .
6 % y0 - condicao inicial do PVI .
7 % xn - ponto final do dominio de interesse .
8 % n - numero de passos desejados .
9 % SAIDA :
10 % x - vetor das abscissas .
11 % y - vetor das ordenadas com as aproximacoes .
12 function [x , y ] = metEuler (f , x0 , y0 , xn , n )
13
14 h = ( xn - x0 ) / n ;
15 x = ( x0 : h : xn ) ';
16 y = zeros ( n +1 ,1) ;
17 y (1) = y0 ;
18
19 for i = 1: n
20 y ( i +1) = y ( i ) + h * f ( x ( i ) ,y ( i ) ) ;
21 end
Agora, se utilizarmos uma regra de integração numérica melhor (regra dos trapézio
e Simpson, por exemplo) conseguimos construir métodos que produzem aproximações
melhores.
Observação 7.2 É importante tomar cuidado pois diferentes bibliografias podem apresen-
tar os métodos de Runge-Kutta com outra expressão. Apesar de terem a mesma ordem do
método apresentado aqui, os resultados obtidos serão distintos.
Observação 7.3 A expressão acima poderia ser escrita em apenas uma linha se substi-
tuíssemos k1 em k2 e k2 em yi+1 . Porém, esta é a forma padrão de apresentar os métodos
de Runge-Kutta pois, além de ser muito mais visível, está de acordo com a estrutura geral
do método.
k1 = h f (x0 , y0 ) = 0, 2 × (2 × 1 × 3) = 1, 2
1
k2 = h f (x0 + h/2, y0 + k1 ) = 0, 2 × (2 × (1 + 0, 2/2) × (3 + 1, 2/2)) = 1, 584
2
y(1, 2) ≈ y1 = y0 + k2 = 4, 584.
Novamente, note que para que y1 não utilizamos o valor de x1 , apenas x0 e x0 + h/2
(ponto médio entre x0 e x1 ).
158 Capítulo 7. Equações Diferenciais Ordinárias
7.2.1 Implementação
16 y = zeros ( n +1 ,1) ;
17 y (1) = y0 ;
18
19 for i = 1: n
20 k1 = h * f ( x ( i ) ,y ( i ) )
21 k2 = h * f ( x ( i ) + h /2 , y ( i ) + k1 /2)
22 y ( i +1) = y ( i ) + k2
23 end
Da mesma forma como feito para o método anterior, não iremos apresentar a
construção do método de quarta ordem, nos limitando a apenas exibir a fórmula. Sendo
assim, o método de Runge-Kutta de 4a ordem (RK4) é dado pela expressão:
k1 = h f (xi , yi )
k2 = h f (xi + h/2, yi + k1 /2)
k3 = h f (xi + h/2, yi + k2 /2) (7.4)
k4 = h f (xi + h, yi + k3 )
1
yi+1 = yi + (k1 + 2k2 + 2k3 + k4 ), i = 0, 1, 2, . . . .
6
k1 = h f (x0 , y0 ) = 0, 2 × 6 = 1, 2
1
y(1, 2) ≈ y1 = y0 + (k1 + 2k2 + 2k3 + k4 ) =
6
1
= 3 + (1, 2 + 2 × 1, 584 + 2 × 1, 66848 + 2, 24087) = 4, 65764.
6
1
y(1, 4) ≈ y2 = y1 + (k1 + 2 × k2 + 2 × k3 + k4 ) =
6
1
= 4, 65764 + (2, 23567 + 2 × 3, 00325 + 2 × 3, 20282 + 4, 40185) = 7, 83258.
6
162 Capítulo 7. Equações Diferenciais Ordinárias
1
y(1, 6) ≈ y3 = y2 + (k1 + 2k2 + 2k3 + k4 ) =
6
1
= 7, 83258 + (4, 38624 + 2 × 6, 01542 + 2 × 6, 50417 + 9, 17552) = 14, 2661.
6
1
y(1, 8) ≈ y4 = y3 + (k1 + 2k2 + 2k3 + k4 ) =
6
1
= 14, 2661 + (9, 13029 + 2 × 12, 8052 + 2 × 14, 0547 + 20, 391) = 28, 1396.
6
1
y(2, 0) ≈ y5 = y4 + (k1 + 2k2 + 2k3 + k4 ) =
6
1
= 28, 1396 + (20, 2605 + 2 × 29, 0851 + 2 × 32, 4384 + 48, 4624) = 60, 1012.
6
7.3. Método de Runge-Kutta de 4ª ordem 163
Perceba que o método RK4 é o que melhor aproxima a solução neste problema. De
fato, o RK4 sempre aproximará melhor a solução do que o método de Euler e RK2.
7.3.1 Implementação
7.4 Exercícios
= 0, y 0 (0) = 0
y(0)
usando h = π/20. Utilize o método que preferir. Dica: Transforme a EDO em uma
sistema de EDOs de primeira ordem.
5. Escreva um script para testar os três métodos estudados (Euler, RK2 e RK4) para
y2
encontrar as aproximações das soluções da EDO y 0 = , no intervalo 1 ≤ t ≤ 2,
t+1
com a condição inicial y(1) = −1/ln(2) e passo h variável. Ao final, o código deve
exibir uma tabela com a seguinte estrutura:
166 Capítulo 7. Equações Diferenciais Ordinárias
Além disso, o script deve plotar o gráfico das 3 soluções aproximadas (em uma
mesma figura).
Os erros devem ser calculados seguindo a expressão ERR = |yn − y(xn )| (diferença
entre a solução exata e a solução aproximada no último ponto) e as taxas devem ser
calculadas seguindo a expressão T AXA = ERROn1 /ERROn2 (razão entre os erros
consecutivos), n1 < n2 .
2 − 2ty
Teste este código com a EDO: y 0 = , no intervalo 0 ≤ t ≤ 1, com condição
t2 + 1
2t + 1
inicial y(0) = 1. A solução exata desta EDO é y(t) = 2 .
t +1
7. O estudo de modelos matemáticos para prever a dinâmica da população de espécies
concorrentes tem sua origem em trabalhos independentes publicados no início deste
século por A. J. Lotka e V. Volterra. Considere o problema de previsão da popu-
lação de espécies, uma que é a predadora, cuja população no instante t seja x2 (t),
alimentando-se da outra, que é a presa, cuja população seja x1 (t).
Vamos supor que a presa sempre tenha abastecimento de alimentos adequado e que
sua taxa de natalidade em qualquer instante é proporcional ao número de presas vivas
7.4. Exercícios 167
Como x01 (t) e x02 (t) representam a variação nas populações de presas e predadores,
respectivamente, com relação ao tempo, o problema é expresso por um sistema de
equações diferenciais não-lineares:
x0 (t) = k1 x1 (t) − k2 x1 (t)x2 (t),
1
Vamos supor que a população de um par particular de espécies seja descrita pelas
equações:
x0 (t) = x1 (t)(4 − 0.0003x1 (t) − 0.0004x2 (t)),
1
em que
• t é o tempo de observação.
• k é a constante da mola.
Dada uma posição inicial x(0) = 1 e um velocidade inicial x0 (0) = 1, estime quanto
tempo o sistema levará para que a amplitude do movimento ficar sempre menor que
0.1. Utilize m = 5, µ = 4 e k = 150.
Utilize o método RK2 para sistemas para calcular a aproximação. O passo de tempo
pode ser escolhido por você. Faça um script para realizar a estimativa. O script deve
plotar o gráfico de x ao longo do tempo.
DICA: Você pode querer trocar o f or do método por um while para atender o que
é pedido no problema.
169
Muitas das funções apresentadas aqui não são totalmente descritas. Para
compreender os detalhes e as diferentes formas de utilizar estas funções você pode acessar
a documentação delas.
Use este capítulo como referência futura para relembrar sintaxes e utilizações
de funções.
Você não precisa memorizar como cada function funciona e o que ela faz, mas a
prática torna a programação muito mais natural e ágil. O que você deve sem dúvida ter é
o entendimento profundo da sintaxe do programa e do seu ambiente.
sua praticidade, essa poderosa ferramenta computacional vem sendo utilizada tanto em
universidades quanto em empresas do mundo todo.
Figura 17 – Algumas das empresas e instituições que utilizam o MATLAB no Brasil. Fonte:
<https://opencadd.com.br/>.
8.1. Sobre o MATLAB 171
Através desta ferramenta é possível ter acesso aos mais diversos códigos criados
e compartilhados pela comunidade de usuários do MATLAB. Os arquivos disponíveis
vão desde pequenas aplicações e métodos (como os método que veremos neste curso)
até bibliotecas completas e complexas de engenharia (como pacote de suporte para
Hardware Arduino, toolboxes para simulações de robótica e detecção de objetos usando
Deep Learning). Sinta-se livre para navegar por esse ambiente e, se necessário, instale as
toolboxes necessárias.
8.1.1 Instalação
2. No canto direito superior, crie uma conta utilizando seu e-mail institucional.
3. Após fazer toda a autentificação da conta, sua licença deve aparecer disponível para
download. O arquivo de instalação deve ter em torno de 226M b.
AVISO: Durante a instalação, será pedido que você escolha quais componentes
gostaria de instalar. Sugiro não instalar todas pois não há necessidade de ocupar
tanto espaço do seu disco. Além do MATLAB, indico as seguintes (outras podem ser
instaladas posteriormente):
DICA: Este layout básico pode ser alterado mudando de posição ou mostrando/escondendo
partes. Isso pode ser feito pelo menu Layout na barra superior ou clicando na margem
superior e arrastando. O layout padrão pode ser retornado pelo menu Layout.
Além destas 4 janelas básicas, alguns outros recursos valem ser mencionados (veja
a figura 19):
2. Estes botões abrem a documentação do MATLAB (que também pode ser acessada
por linha de código na janela de comandos ou pela tecla F 1). Esta documentação
contém uma descrição detalhada de todas as funções e métodos pré-implementados
pelo programa com exemplos em muitos casos. Essa documentação também pode
ser encontrada na página da MathWorks1 .
3. Botão para login e logout na sua conta da MathWorks. Geralmente este login é
automático depois da primeira vez, mas é sempre interessante verificar se ele está
ativo.
1
Toda a documentação está escrita em inglês, mas neste capítulo busquei tratar das principais funções
que serão necessárias
174 Capítulo 8. MATLAB básico para Cálculo Numérico
4. A aba Apps dá acesso a diversas ferramentas específicas que podem ser instaladas,
desinstaladas e até mesmo criadas conforme a sua necessidade. Diferentes apps estarão
disponíveis dependendo das toolboxes que você instalou. Talvez o mais interessante
dentro do cálculo numérico seja o Curve Fitting para ajuste de curvas.
5. O botão Import Data permite carregar dados a partir de arquivos (xlsx, txt, cvs,
...). Apesar de ser uma ferramenta intuitiva e prática para uso pessoal, quando
for necessário, faremos a importação por linha de comando para evitar repetições
desnecessárias.
6. A aba Plots mostra todas as diferentes possibilidades de gráficos que podem ser
gerados. Se você tiver dados selecionados no seu Workspace ele mostrará em destaque
todas as funções que aceitam o conjunto de dados selecionados. Na prática, iremos
gerar os gráficos através de linhas de código, mas esta aba permite você conhecer as
possibilidades (a documentação apresentará exemplos).
7. Através deste botão é possível navegar pelas pastas do seu computador e alterar o
diretório de trabalho.
8. O botão New Script abrirá o editor do MATLAB, o que também pode ser feito pela
janela de comandos. Na seção 8.4 isso será tratado em detalhes.
Por fim, o temos a janela do Editor onde é possível criar funções ou rotinas (também
conhecidas como script), salvá-las para utilização posterior, além de ter ferramentas que
auxiliam a encontrar erros no código (conhecido como debbuger). Esta parte essencial na
implementação de códigos é tratada com detalhes em 8.4.
AVISO: É obrigatório que os arquivos que serão executados e demais arquivos necessários
para a execução estejam na mesma pasta (current folder). Caso isso não ocorra, mensagens
de erro ou avisos (como descrito em 8.9) podem ocorrer.
8.2. Aspectos Gerais 175
Na janela de comandos, vamos criar algumas variáveis para testar algo ao longo do
texto. Primeiramente, declaramos 2 variáveis numéricas (digite e depois pressione Enter
para que o comando seja executado):
1 >> a = 1
2 a =
3 1
4 >> b = 2
5 b =
6 2
176 Capítulo 8. MATLAB básico para Cálculo Numérico
DICA: O símbolo >> indica o ponto de entrada para informações e comandos. Não é
possível editar comandos que já tenham sido executados.
1 >> c = a + b
2 c =
3 3
4 >> d = a - b
5 d =
6 -1
Neste momento, você deve notar que no workspace (ambiente de trabalho) estão
listadas as 4 variáveis que criamos e a informação contida nelas2 .
• clc: Limpa a janela de comandos, porém, não apaga as variáveis declaradas. Teste
este comando e veja o efeito;
AVISO: Comandos como o lookfor inverse ou código de médio a grande porte podem
demandar um tempo considerável na execução. Se por algum motivo desejarmos que o
programa interrompa a execução, podemos utilizar o comando Ctrl+C para abortar (em
casos de sobrecarga de memória este comando pode demorar para ser executado).
DICA: As setas direcionais para cima e para baixo do teclado auxiliam a navegar pelo
histórico de comandos. Com isso evitamos a necessidade de reescrever comandos longos.
Se você utilizou o clear nas variáveis declaradas a pouco pode retornar aos comandos
que usamos para declarar as variáveis e refazer essas atribuições.
Criamos várias variáveis ao longo dos código que implementamos. Estas variáveis
podem ter os nomes mais diversos possíveis. Algumas regras a respeito do nome das
variáveis:
• Pode possuir de 1 até 63 caracteres. É claro que criar variáveis com nomes
muito longos torna a digitação morosa, mas sempre que possível usamos nomes que
remetam ao significado que ela possui. Por exemplo, podemos alocar a media de um
conjunto de valores por media ao invés de simplesmente m. Isso torna o código muito
mais fácil de ser compreendido.
• Não utilizar nomes de functions internas. Por exemplo, não devemos criar
uma variável com o nome det ou area pois estes já são nomes de functions do
MATLAB.
• Podemos utilizar números nos nomes das variáveis. Podemos, por exemplo,
criar variáveis x1 e x2 e atribuir informações a elas.
• Ainda no quesito de numerações, o nome das variáveis não podem ser iniciadas
como números. Isto é, não podemos criar a variável com nome 1x.
Além do nome de functions existem alguns outros nomes que devem ser evitados
para não causar problemas indesejados ao longo dos códigos:
• ans: é a variável padrão de resultado para o caso da resposta de uma conta não ter
uma variável para ser alocada. Será sobrescrita sempre que necessário. Por exemplo,
se você digitar na janela de comandos:
1 >> 1 + 2
2 ans =
3 3
• Inf : infinito (exemplo: 1 ÷ 0). A menos que seja esperado, geralmente indica um
erro de implementação do código.
Dado que o propósito do MATLAB é ser uma ferramenta científica, é natural que
utilizemos a notação científica. Assim como na maioria das linguagens, no MATLAB a
notação científica tem a forma:
Ou seja, primeiras casas decimais, seguido pela letra e, o sinal da potência e por último a
potência.
Encerramos esta seção de comandos iniciais falando sobre o ponto e vírgula. Vimos
que ao fazer atribuições de valores as variáveis na janela de comandos o resultado era
sempre exibido em seguida, isto é:
180 Capítulo 8. MATLAB básico para Cálculo Numérico
1 >> a = 1
2 a =
3 1
4 >> b = 2
5 b =
6 2
Porém, muitas vezes não estamos interessados em “poluir” a janela de comandos com
informações irrelevantes (resultados intermediários de um método por exemplo). Para
evitar isso, utilizamos o ponto e vírgula para omitir a exibição dos resultados:
1 >> a = 1;
2 >> b = 2;
3 >> a
4 a =
5 1
6 >> b
7 b =
8 2
Como é possível ver, nas duas primeiras linhas os comandos foram executados e as
atribuições realizadas, porém precisamos digitar o nome da variável e apertar Enter caso
desejemos visualizar o que está armazenado na variável.
Utilize o ponto e vírgula nos código sempre que deseja omitir a exibição
de uma atribuição ou queira fazer a exibição de forma mais agradável (iremos falar
sobre isso mais à frente). Isso será muito útil dentro das estruturas de repetição em 8.7.
1 >> A = [1 2 3 ; 4 5 6 ; 7 8 9]
2 A =
3 1 2 3
4 4 5 6
5 7 8 9
Explicando:
Note que não houve nenhum necessidade de declarar a variável A e seu tamanho
previamente. Além disso, é claro que a construção acima também pode ser usada para
definir um vetor.
IMPORTANTE: Por padrão iremos sempre assumir que um vetor é coluna. Isso evita
diversos problema dimensionamento de variáveis.
AVISO: É claro que a compatibilidade das dimensões precisa ser respeitadas. Por exemplo,
não podemos somar uma matriz 3 × 3 com uma 4 × 4. No entanto, veremos que é muito
comum realizar manipulações nas quais atribuímos a matriz 3 × 3 a um bloco/parte de
uma matriz 4 × 4. Veremos como fazer isso mais à frente.
1 >> A = [1 2 3 ; 4 5 6 ; 7 8 9];
2 >> B = [1 2 3 ; 4 5 6 ; 7 8 10];
3 >> A * B % Multiplicacao matricial usual .
4 ans =
5 30 36 45
6 66 81 102
7 102 126 159
8
9 >> A .* B % Aqui de cada componente de A pelo seu
correspondente de B .
10 ans =
11 1 4 9
12 16 25 36
13 49 64 90
14
15 >> A ./ B % Divisao componente a componente .
16 ans =
17 1 1 1
18 1 1 1
19 1 1 0.9
20
21 >> A ' % Transposta de matriz .
8.3. Matrizes e Vetores 183
22 ans =
23 1 4 7
24 2 5 8
25 3 6 9
13 2
14 5
15 9
AVISO: Os parênteses são utilizados, como de costume, para definir qual operação
será realizada primeiro. Quando for necessários agrupar mais de um par de parênteses
continuamos a utilizá-los e não utilizamos colchetes e chaves. Isso porque os colchetes são
usados para definir matrizes e as chaves são usadas na definição de um tipo de estrutura
chamada “célula” (em inglês, cell array).
8.3.2 Indexação
Antes de falar como realizar esta busca ao longo de um vetor vamos entender como
fazer e quais as possibilidades básicas de manipulações usando índices. Depois, na seção
8.7.1, tratamos de operadores lógicos para condições e seleções.
8.3. Matrizes e Vetores 185
Índices
Em diversos momentos dos códigos dos métodos desta apostila (ou qualquer outro
código) precisamos manipular informações dentro de uma matriz ou vetor. A indexação
no MATLAB é feita entre parênteses, separada por vírgula e, no caso de
matrizes segue é ordem “linha” e depois “coluna”.
Por exemplo:
1 >> A = [1 2 3 ; 4 5 6 ; 7 8 9]
2 A =
3 1 2 3
4 4 5 6
5 7 8 9
6 >> A (2 ,3)
7 ans =
8 6
DICA: Podemos usar dois índices para indexar um vetor, porém, um deles deve ser igual
a 1, é claro.
186 Capítulo 8. MATLAB básico para Cálculo Numérico
Usando a mesma sintaxe dos exemplos acima podemos alterar informações em uma
variável. Por exemplo, o comando abaixo irá atribuir π a componente da matriz A da
primeira linha e segunda coluna:
1 >> A (1 ,2) = pi
2 A =
3 1.0000 3.1416 3.0000
4 4.0000 5.0000 6.0000
5 7.0000 8.0000 9.0000
1 >> size ( A )
2 ans =
3 3 3
4 >> A (4 ,2) = 10
5 A =
6 1.0000 3.1416 3.0000
7 4.0000 5.0000 6.0000
8 7.0000 8.0000 9.0000
9 0 10.0000 0
10 >> size ( A )
11 ans =
12 4 3
Dessa forma, podemos construir um vetor (ou matriz) que ainda não sabemos qual
o tamanho sem nos preocupar com as dimensões.
8.3. Matrizes e Vetores 187
AVISO: Apesar desta característica propiciar alguns vantagens, pagamos um preço caro
por ela. Caso alteremos a dimensão de uma variável diversas vezes, dentro de um loop por
exemplo, é possível que o código torne-se desnecessariamente lento. Isso ocorre porque o
programa precisa fazer uma série de operações para alterar o espaço ocupado pela variável
na memória do computador. Para contornar isso podemos criar uma variável previamente
do tamanho correto usando a function zeros por exemplo. Essa técnica é frequentemente
utilizada nesta apostila.
Vetores sequenciais
Criar matrizes e vetores da forma como apresentamos pode ser problemático quando
estes forem de tamanho um pouco maior, e em muitas aplicações isso será necessário.
Por hora vamos nos concentrar em construir um vetor com valores igualmente
espaçados. Isso é muito útil para fazer gráficos, por exemplo. Suponha que queremos
construir o vetor com os números de 0 até 1 com passo de 0.25. Para isso, podemos usar o
comando:
1 >> v = 0:0.25:1
2 v =
3 0 0.2500 0.5000 0.7500 1.0000
1 <Variável> = <Início>:<Passo>:<Fim>
1 >> v = 0:5
2 v =
3 0 1 2 3 4 5
DICA: Note que o vetor criado é linha. Portanto, devemos transpô-lo: v = (0:5)'.
188 Capítulo 8. MATLAB básico para Cálculo Numérico
O operador “:”
Como vimos no caso dos vetores sequenciais, os dois pontos “:” é usado para
determinar intervalos. Podemos usar esta noção para extrair informações ou blocos de
uma matriz.
1 >> A = [1 2 3 ; 4 5 6 ; 7 8 9]
2 A =
3 1 2 3
4 4 5 6
5 7 8 9
6 >> A (1:3 ,2)
7 ans =
8 2
9 5
10 8
1 >> A (3 ,:)
2 ans =
3 7 8 9
Por fim, podemos combinar a seleção de linhas e colunas. Isso possibilita extrair
blocos:
8.3. Matrizes e Vetores 189
Usando a mesma ideia da seção anterior, podemos usar os colchetes para criar o
vetor de índice que desejarmos. Por exemplo, na matriz A dada na seção acima, obtemos
as linhas 1 e 3 fazendo:
1 A = [1 2 3 ; 4 5 6 ; 7 8 9]
2 A =
3 1 2 3
4 4 5 6
5 7 8 9
6 >> A ([1 3] ,:)
7 ans =
8 1 2 3
9 7 8 9
Sendo assim, podemos trocar duas linhas de uma matriz usando estes comando:
Concatenação
1 >> A = [1 2 3 ; 4 5 6 ; 7 8 9]
2 A =
3 1 2 3
4 4 5 6
5 7 8 9
6 >> v = [10 20 30] '
7 v =
8 10
9 20
10 30
11 >> c = 100
12 c =
13 100
1 >> G = [ A v ; v ' c ]
2 G =
8.4. Editor 191
3 1 2 3 10
4 4 5 6 20
5 7 8 9 30
6 10 20 30 100
8.4 Editor
Até o momento viemos apresentando contas para serem realizadas na Janela de
comandos pois nosso intuito era apenas apresentar um pouco da sintaxe do programa. Na
prática, ao resolver problemas mais interessantes e menos imediatos do que um sistema
linear precisamos escrever mais linhas de código. Além disso, é muito importante que
sejamos capazes de reutilizar uma sequência de comandos (sem ter que redigitá-los toda vez),
transferir códigos de um local para o outro e testar um código com diversos parâmetros.
Para suprir essa necessidade o MATLAB possui uma janela chamada de Editor.
Esse editor nada mais é do que um bloco de notas com diversas ferramentas que auxiliam
na programação de códigos na linguagem do MATLAB. De fato, os arquivos .m criados
podem ser abertos em qualquer bloco de notas, porém não teríamos as ferramentas para
auxiliar e nem poderíamos testar os códigos.
Após fazer uma das três opções acima, no layout padrão, o MATLAB deve aparecer
como na figura 20. Como é possível ver nesta figura, você a janela do programa dividida
em duas, acima o Editor e abaixo a Janela de Comandos. Na aba superior do Editor você
encontrará todos os seus arquivos que estão abertos (na imagem temos apenas um arquivo
Untitled).
Além disso, quatro regiões novas se abrirão e que são relevantes para nós:
1. Opções para criar novos arquivos (Ctrl+N), abrir (Ctrl+O) e salvar (Ctrl+S).
192 Capítulo 8. MATLAB básico para Cálculo Numérico
DICA: Apesar de ser uma questão de gosto pessoal, é costumeiro utilizarmos o Editor no
modo “Undocked”, ou seja, separado do restante do MATLAB. Isso permite aumentar o
campo de visão pois o Editor será aberto em uma janela individual. Para fazer ou desfazer
isso você pode clicar no triângulo invertido no canto direito superior do editor (ao lado do
×) e escolher a opção Undock. O atalho para isso é Ctrl+Shift+U.
No Editor é possível criar dois tipos de arquivos básicos (ambos com formato *.m):
AVISO: Existem ainda os arquivos do tipo Live Script (e alguns outros tipos). Porém,
não entraremos neste tipo de arquivo aqui. Caso você se interesse, leia sobre como eles
funcionam (bem simples) e pode utilizar este formato.
• Parênteses e colchetes tem sua contraparte destacada ao passar o cursor por cima.
• O sinal de atribuição “=” fica destacado caso não haja ponto e vírgula no final.
DICA: Fazer comentários ao longo dos códigos é altamente recomendado. Seja em scripts
ou functions, os comentários permitem que o programador organize o código, indique o
significado e tipo de determinadas variáveis, registre a explicação de trechos importantes
para futuras consultas e permite que outras pessoas compreendam com muito mais
facilidade o que o código faz. Veja a forma como os códigos ao longo da apostila foram
comentados para entender como eles podem ser feitos.
8.4.1 Functions
IMPORTANTE: Uma regra precisa ser sempre seguida: o nome do arquivo que
contém a function deve ser idêntico ao nome da function.
4
As funções matemáticas retornam apenas uma informação e por isso as functions são um conceito mais
abrangente. As variáveis de entrada e saída podem ser desde números até matrizes, funções algébricas,
outras function, caracteres de texto, etc.
8.4. Editor 195
AVISO: Além da regra acima, existem algumas limitações em relação ao nome das
functions e scripts (e por consequência do nome dos arquivos). Estas limitações são as
mesmas para nomes de variáveis, isto é: sem conflitar com nome de functions pré-existentes;
não começar com números; sem caracteres especiais e sem espaço.
DICA: Na sintaxe das functions, as variáveis de entrada ficam a direita, entre parênteses
e separadas por vírgula. Já as variáveis de saída ficam a esquerda (antes do sinal de igual),
entre colchetes e separadas por vírgula. Essa estrutura é muito semelhante a sintaxe de
funções matemáticas, por exemplo z = f (x, y), em que a função f recebe x e y e retorna z.
Exemplo 8.1 A function a seguir recebe dois valores a e b, calcula a soma e a diferença
deles e retorna estes valores.
Após salvar o arquivo (lembre que nome do arquivo deve ser igual ao nome da function)
podemos testar esta function na Janela de comandos:
Do exemplo acima vemos que a sintaxe para utilizar uma function é igual a
definição dela (a menos dos nomes das variáveis de entrada e saída que podem mudar).
196 Capítulo 8. MATLAB básico para Cálculo Numérico
• Tentar acessar/usar uma variável dentro de uma function que está alocada fora do
workspace dela.
DICA: Neste último item é importante destacar que é possível criar, por exemplo, uma
variável n dentro de uma function e outra variável n fora sem causar qualquer conflito de
informação.
Exemplo 8.2 A function a seguir recebe uma matriz A de dimensão 2 × 2 (não é feita a
verificação das dimensões), calcula o determinante det(A) = a12 a21 − a11 a22 e retorna esse
valor.
• Uma function cujo nome é A e está sendo avaliada em 1 (primeiro valor de entrada)
e 2 (segundo valor de entrada).
8.4.2 Scripts
O segundo tipo de arquivo que podemos criar no Editor são os scripts. Diferente
das functions, não temos um cabeçalho indicando que o arquivo é deste tipo. Na prática,
se o arquivo não começar com function ele é automaticamente um script.
Além disso, scripts não possuem variáveis de entrada e saída pois utilizam
como workspace do próprio MATLAB. Por causa disso, os scripts podem ser pensados
como uma sequência de comandos que poderiam ter sido executados na Janela de comandos,
mas que optamos por salvar em um arquivo.
Como os scripts não possuem variáveis de entrada e saída, para executá-los basta
digitar o nome do arquivo na Janela de comandos ou usar o F5 no editor (veja os exemplos
abaixo).
Exemplo 8.4 A figura 25 ilustra o teste function det2x2 através de um script para uma
matriz escolhida. Por hora, não se preocupe com o disp na última linha.
8.4. Editor 201
8.4.2.1 input
Muitos códigos encontrados na internet fazem uso de uma function chamada input
nos scripts e até mesmo functions. Esta function serve para que, ao chegar nesta linha
durante a execução, o código faça uma pausa e aguarde até o usuário insira alguma
informação e aperte Enter. Com isso, é possível criar comandos para que um usuário digite
dados com os quais quer testar um código.
Apesar de ser muito didática, esta function é altamente ineficaz para a implemen-
tação de problemas práticos e sua utilização é extremamente não recomendada. Como
alternativa, é sugerido que as variáveis e demais informações (como leitura de arquivos)
seja feita dentro do script principal.
Exemplo 8.5 Problema: Criar uma function que recebe um vetor e troca dois elementos
de posição.
1 v ( pos1 ) = v ( pos2 ) ;
2 v ( pos2 ) = v ( pos1 ) ;
1 >> exemploTroca
1 % Script para testar a function 2 v =
troca2 . m 3 0
2 4 0.1
3 v = [0 0.1 0.2 0.3] '; % vetor . 5 0.2
4 L1 = 2; 6 0.3
5 L2 = 4; 7 v =
6 v 8 0
7 v = troca2 (v , L1 , L2 ) ; 9 0.3
8 v 10 0.2
11 0.1
Exemplo 8.6 Problema: Criar uma function que recebe um vetor e calcula a norma
dele.
A primeira forma (com somatório) faremos mais adiante. Por enquanto vamos fazer a
segunda forma. Usando as operações da tabela 7 podemos construir o código:
204 Capítulo 8. MATLAB básico para Cálculo Numérico
Ou seja, o código recebe como variável de entrada o vetor x, faz a operação para
obter a norma do vetor e armazena na variável y, que é retornada como variável de saída.
O script abaixo mostra o funcionamento do código.
abs
1 >> C = [ -1 2 ; -4 -2]
2 C =
3 -1 2
4 -4 -2
5 >> C2 = abs ( C )
6 C2 =
7 1 2
8 4 2
det
1 >> A = [1 2 3 ; 4 5 6 ; 7 8 10]
2 A =
3 1 2 3
4 4 5 6
5 7 8 10
6 >> d = det ( A )
7 d =
8 -3.0000
diag
Caso a variável de entrada seja uma matriz, retorna um vetor com os elementos
da diagonal desta matriz. Caso a variável de entrada seja um vetor, retorna uma matriz
diagonal com os elementos do vetor dado.
1 >> A = [1 2 3 ; 4 5 6 ; 7 8 9]
2 A =
3 1 2 3
4 4 5 6
206 Capítulo 8. MATLAB básico para Cálculo Numérico
5 7 8 9
6 >> v = diag ( A )
7 v =
8 1
9 5
10 9
11 >> diag ( v )
12 ans =
13 1 0 0
14 0 5 0
15 0 0 9
eye
inv
Calcula a inversa de uma matriz quadrada inversível. Caso a matriz não seja
quadrada uma mensagem de erro será exibida. Caso a matriz seja singular (não-inversível),
calculará uma pseudoinversa e dará um aviso sobre isso. Veja 8.9 sobre como lidar com
estas mensagens e avisos.
1 >> A = [1 2 3 ; 4 5 6 ; 7 8 10]
2 A =
3 1 2 3
4 4 5 6
5 7 8 10
8.5. Funções Básicas 207
6 >> inv ( A )
7 ans =
8 -0.6667 -1.3333 1.0000
9 -0.6667 3.6667 -2.0000
10 1.0000 -2.0000 1.0000
length
max
Caso a variável de entrada seja um vetor, retorna o valor da maior das componentes.
Caso a variável de entrada seja uma matriz, retorna um vetor com o máximo de cada
coluna.
DICA: Tanto a function max quanto a mim tem a opção de uma segunda variável de saída,
que conterá o índice no qual o máximo ou o mínimo ocorreu pela primeira vez nos dados
fornecidos.
min
ones
Cria uma matriz de dimensão dada com todas as componentes iguais a um.
8 1 1 1
9 1 1 1
prod
1 >> v = [1 2 3 4] ';
2 >> p = prod ( v )
3 p =
4 24
rand
Produz uma matriz, de dimensão dada, com componentes com valores aleatórios
entre 0 e 1. Cada chamada da function cria uma matriz diferente. Caso a matriz seja
quadrada, ela será inversível.
DICA: A function rand é ideal para testar códigos envolvendo matrizes pois permite
criá-las de qualquer dimensão desejada facilmente.
size
4 3 4
5 >> [m , n ] = size ( A )
6 m =
7 3
8 n =
9 4
Podemos incluir uma segunda variável de entrada para obter apenas uma das
dimensões. Usamos 1 para a primeira dimensão (número de linhas) e 2 para a segunda
(número de colunas).
sum
1 >> v = [1 0 2] ';
2 >> sum ( v )
3 ans =
4 3
5 >> ( sum ( v .^2) ) ^(1/2) % Esta eh a norma do vetor v ( raiz
quadrada da soma dos quadrados de cada componente ) .
6 ans =
7 2.2361
8.5. Funções Básicas 211
zeros
Cria uma matriz de dimensão dada com todas as componentes iguais a zero.
8.5.1 Polinômios
Para as functions desta seção será necessário que o pacote Symbolic Math Toolbox.
Caso você não saiba se possui esta biblioteca instalada, execute o código:
Neste caso, 1 significa que a biblioteca está instalada. Caso você não possua essa
biblioteca instalada, procure e instale ela pelo Add-On Explorer.
1 >> syms x
2 >> x
3 x =
4 x
5 >> y = x ^2
212 Capítulo 8. MATLAB básico para Cálculo Numérico
6 y =
7 x ^2
8 >> z = diff ( y ) % Derivada de y em relacao a x .
9 z =
10 2* x
11 >> z = int ( y ) % Integral de y em relacao a x .
12 z =
13 x ^3/3
14 >> z = int (y ,0 ,1) % Integral de y em relacao a x no intervalo
[0 ,1].
15 z =
16 1/3
17 >> z = y * y + x ^3
18 z =
19 x ^4 + x ^3
DICA: Além dos comandos acima, algumas functions relacionadas a manipulação algébrica
são úteis: simplify, factor, expand, partfrac, pretty. Veja a documentação de cada
uma para entender seu funcionamento.
A function subs é útil para lidar com o resultado de alguma conta ou procedimento
feito com variáveis simbólicas pois substitui um valor ou termo em uma expressão:
1 >> syms x
2 >> y = x ^2
3 y =
4 x ^2
5 >> subs (y ,x ,2)
6 ans =
7 4
8 >> subs (y ,x , sin ( x ) )
9 ans =
10 sin ( x ) ^2
8.5. Funções Básicas 213
1 >> syms x
2 >> solve ( x ^2 - 2* x - 1 == 0)
3 ans =
4 1 - 2^(1/2)
5 2^(1/2) + 1
1 >> syms w ( t )
2 >> Dw = diff ( w ) ;
3 >> D2w = diff (w ,2) ;
4 >> w = dsolve ( diff ( D2w ) == -w , w (0) ==1 , Dw (0) ==0 , D2w (0) ==0)
% w ' ' = -w com condicoes iniciais .
5 w =
6 exp ( - t ) /3 + (2* exp ( t /2) * cos ((3^(1/2) * t ) /2) ) /3
7 >> w = dsolve ( diff ( D2w ) == -w ) % Solucao geral de w ' ' = -w .
8 w =
9 C3 + exp ( - t ) /3 + C2 * t + (2* exp ( t /2) * cos ((3^(1/2) * t ) /2) ) /3 + (
C1 * t ^2) /2
A tabela 8 apresenta algumas functions para lidar com valores não inteiros que
podem ser úteis. Consulte a documentação individual caso precise de alguma delas.
A primeira forma que podemos fazer para declarar uma função algébrica é criar
uma function que recebe uma variável de entrada x e retorna um valor y. Por exemplo,
1 function y = f ( x )
2
3 y = x ^2;
Apesar desta opção ser válida e muito comum não iremos utilizá-la pois cria uma
quantia desnecessária de arquivos pequenos. Além disso, não tem vantagens no tempo de
execução em relação a uma das formas que apresentaremos.
f (x, y) = sen(x) + ey
1 >> f ( pi ,1)
2 ans =
3 2.7183
Esta forma permite usar f como variável de entrada em uma function (criada por
nós ou própria do MATLAB). Você verá isso ocorrer com frequência nesta apostila.
sqrt
2 ans =
3 1.0000
4 1.4142
5 1.7321
exp
log e log10
Para criar uma variável deste tipo inserimos os caracteres na ordem desejada entre
aspas simples ou duplas. Como você pode ver na figura 26, usar um par de aspas simples
ou de aspas duplas criam variáveis de classes (tipo) diferente.
Na figura 26, a variável a é uma char e pode ser tratada como um vetor de cinco
componente. De fato, podemos usar as functions length e size neste tipo de variáveis:
1 >> size ( a )
2 ans =
3 1 5
1 >> a '
2 ans =
3 't '
4 'e '
5 'x '
6 't '
7 'o '
8 >> a (2) = 'E '
9 a =
10 ' tExto '
218 Capítulo 8. MATLAB básico para Cálculo Numérico
AVISO: Devemos tomar cuidado em não misturar variáveis do tipo char com variáveis
numéricas.
A possibilidade de lidar com variáveis do tipo string traz muitas vantagens para
quem trabalha, por exemplo, com machine learning. No entanto, nesta apostila vamos
nos limitar apenas ao que elas permitem fazer no sentido de exibição de mensagens e
resultados.
Diversas funções são úteis para manipular variáveis do tipo string, veja a documen-
tação buscando pela palavra “string” para conhecer algumas. Talvez a mais útil seja o
símbolo de soma (+) que faz o papel de união entre variáveis.
Duas functions ajudam muito a lidar com variáveis de texto. Podemos utilizá-las
para tornar a apresentação de resultados mais clara.
disp
Do inglês display, esta é uma das principais formas de exibir informações de forma
organizada. A forma mais simples de utilizá-la é passando como variável de entrada a
informação que desejamos exibir. Por exemplo, se queremos mostrar uma matriz podemos
usar:
DICA: Note como a parte “A = ”, muitas vezes irrelevante para quem está executando o
código, é omitida ao usarmos disp.
A forma mais avançada de utilizar esta function é lembrar que as variáveis de texto
podem ser tratadas como vetores e, portanto, podem ser concatenadas. O único porém
aqui é que variáveis numéricas não podem ser misturadas com strings. Para contornar
isso, utilizamos a function num2str que converte números em textos7 . Assim, podemos
escrever:
Os passos feitos neste caso são: converter o número 4 para o seu equivalente em texto,
concatenar as strings usando os colchetes e usar o disp para exibir o resultado.
Utilizando aspas duplas para que o texto escrito seja uma variáveis do tipo string
teremos como na figura 27. Lembre-se que neste caso o símbolo de adição denota a união
entre as duas informações.
Exemplo 8.8 Vimos no exemplo 8.6 um código que recebe um vetor e calcula a norma
dele. Sem mexer na function, poderíamos tornar a resposta do código mais agradável
fazendo o script como abaixo.
7
O número 2 em inglês tem a pronúncia muito similar a palavra “para” (two e to).
220 Capítulo 8. MATLAB básico para Cálculo Numérico
4 y = norma_v1 ( x ) ;
5
6 disp ( 'A norma do vetor eh : ')
7 disp ( y )
fprintf
Esta function tem sua sintaxe herdada de linguagens de baixo nível como o C e
são razoavelmente complexas de ser utilizadas. Os exemplos abaixo foram retirados da
documentação do MATLAB na function sprintf (similar a fprintf), consulte-a para ver
mais possibilidades.
DICA: A estrutura “%5.2f” significa que queremos inserir um número em ponto flutuante,
queremos utilizar 2 casas decimais e ao menos 5 espaços para a parte inteira. Se a parte
inteira tiver mais dígitos o programa acrescente automaticamente e se tiver menos ele
deixará espaços em branco.
Por causa desta razões é necessário ter formas eficientes de realizar seleções e
repetições. O MATLAB, assim como a maioria das linguagens estruturadas, possuem
estruturas para atender estas necessidades. Saber combiná-las para criar um pro-
cesso que realiza eficientemente as tarefas desejadas é onde reside a beleza da
programação.
Antes de falar das estruturas precisamos falar sobre os operadores lógicos disponíveis.
Eles permitem uma série de oportunidade dentro dos códigos e são essenciais para as
estruturas de seleção.
Alguns exemplos:
1 >> 10 > 9
2 ans =
3 logical
4 1
5 >> 10 < 9
6 ans =
7 logical
8 0
9 >> 2 + 2 == 4
10 ans =
11 logical
12 1
13 >> 3 + 4 ~= 7
14 ans =
15 logical
16 0
Além dos 6 operadores listadas, outros 3 são essenciais para os códigos construídos
nesta apostila. Eles servem para combinar duas expressões como as acima. Este operadores
estão listados na tabela 11.
O símbolo de negação (∼) serve para negar uma sentença dada. Por exemplo, a
sentença abaixo pode ser lida como “10 não é menor que 9?”:
2 ans =
3 logical
4 1
Como pode ser visto a resposta desta pergunta é sim pois dizer “10 não é menor que 9” é
equivalente a “10 é maior ou igual a 9”, que é verdade.
DICA: Note que o símbolo de negação já é usado também no símbolo lógico de não-
igualdade (diferente) ∼=. O símbolo literalmente é uma negação da igualdade.
É claro que a resposta desta sentença é falso pois, apesar da primeira ser verdadeira, a
segunda é falsa.
DICA: Caso deseje, você pode usar parênteses para organizar a expressão: (10 > 9)&
(11 < 10). Porém, não é algo obrigatório.
Por último temos o operador lógico OU. Neste caso, apenas uma das sentenças
precisa ser válida. No exemplo anterior, teríamos:
pois a primeira parte da sentença é verdadeira, o que torna a sentença inteira verdadeira.
Todos os operadores lógicos podem ser usados na forma vetorial, isto é, para
comparar várias instâncias simultaneamente. Por exemplo:
Podemos combinar a forma acima com a indexação da variável para fazer atribuições
ou manipulações:
Dessas forma, atribuímos 1 as entradas de b onde a condição a > 0.7 é válida (segunda e
terceira componente).
8.7. Estruturas de seleção e repetição 225
8.7.2 if
A estrutura básica do if é:
1 if <Condição Booleana>
2 <Ações>
3 end
Desta forma, tudo que está entre o if e o end correspondente serão executados
caso a condição booleana seja verdadeira e não serão executados caso contrário.
Além da estrutura básica podemos incluir o else (“senão”) para o caso em que a
condição booleana seja falsa:
1 if <Condição Booleana>
2 <Ação 1>
3 else
4 <Ação 2>
5 end
IMPORTANTE: O else não possui condição booleana. Isso porque a Ação2 será
executada quando a condição booleana do if for falsa.
Ainda, para incluir diversas condições podemos usar o elseif quantas vezes forem
necessárias:
4 <Ação 2>
5 elseif <Condição Booleana 3>
6 <Ação 3>
7 else
8 <Ação 4>
9 end
Neste caso, a condição booleana 1 é testada primeiro, caso ela seja falsa, a condição
booleana 2 é testada e assim por diante. Note que foi utilizado apenas um end para toda
a estrutura.
Observação 8.1 A forma geral que usa elseif poderia ter sido escrita usando 3 if
encaixados da seguinte forma:
Exemplo 8.9 (Par-Ímpar) Problema: Criar uma function que recebe um número in-
teiro positivo e exibe na tela se ele é par ou ímpar.
8.7. Estruturas de seleção e repetição 227
1 if mod (n ,2) == 0
2 disp ( 'O numero eh par ')
3 else % Caso contrario ( resto == 1)
4 disp ( 'O numero eh impar ')
5 end
1 function parImpar ( n )
2
3 if mod (n ,2) == 0
4 disp ( 'O numero eh par ')
5 else % Caso contrario ( resto == 1)
6 disp ( 'O numero eh impar ')
7 end
Podemos ainda melhorar um pouco nosso código introduzindo uma análise para
saber se n é, de fato, um número inteiro positivo. Para testar a positividade basta usar uma
desigualdade comum n >= 0. Agora, para testar se um número é inteiro, vamos testar se
este número é igual ao número obtido ao descartar as casas decimais, isto é, apenas um
número inteiro será igual a ele próprio depois de descartar as casas decimais. Para isso,
podemos usar a function fix. A condição completa é if n >= 0 && n == fix(n) e o
código final é:
8.7.3 switch
Exemplo 8.10 (Divisibilidade por 3) Problema: Criar uma function que recebe um
número inteiro positivo e exibe na tela o resto da divisão por 3.
8.7.4 while
Ou s eja, o código irá repetir as ações dadas até que a condição booleana deixe de ser
verdadeira. Mais especificamente, ao chegar no while o código irá verificar se a condição
booleana é verdadeira pela primeira vez. Se ela for verdadeira irá executar quaisquer ações
indicadas dentro da estrutura até chegar ao end. Em seguida, ele retorna ao while e
verifica se a condição continua verdadeira. Se continuar, repete as ações indicadas, senão,
sai da estrutura e segue para as linhas que está após do end sem executar novamente.
Pelo “caminho” que o código segue o while (e o for da próxima seção), cada
repetição que ocorre é chamada de loop ou laço.
8.7. Estruturas de seleção e repetição 231
temos que perceber que este conjunto segue a regra xi = 2 + 0.25(i − 1), com i = 1, . . . , 5.
Exemplo 8.11 (Mensagem repetida) Problema: Criar uma function que recebe uma
mensagem (texto) e número inteiro positivo n e exibe esta mensagem na tela n vezes.
Solução: Para implementar este código iremos utilizar um contador, isto é, uma
variável cuja função é guardar a informação de quantas vezes a repetição foi realizada.
Denotaremos por k este contador. Começamos com k recebendo o valor 1 e a cada repetição
adicionamos 1 à variável para aumentar a contagem.
Como k está contando o número de repetições, a condição booleana pode ser k <= n.
Dessa forma, k percorrerá os valores de 1 até n, mas não permitirá que a próxima repetição
seja executada. O código final fica como abaixo:
7 end
Exemplo 8.12 Problema: Criar uma function que recebe um número inteiro positivo n
e divide-o por 2 até ficar menor que 1. Ao final retorna o número obtido e a quantidade de
repetições necessárias.
3 0.6250
4 k =
5 5
6 >> [n , k ] = dividePor2 (100)
7 n =
8 0.7813
9 k =
10 8
8.7.5 for
Exemplo 8.13 Problema: Criar uma function que recebe três valores a, b e n (inteiro
positivo) e retorna o vetor sequencial com extremidades a e b e passo h = (b − a)/n.
234 Capítulo 8. MATLAB básico para Cálculo Numérico
Solução: Como já visto, este vetor poderia ter sido criado simplesmente usando o
comando v = a:h:b, após declarar h é claro. Porém, para entender o funcionamento do
for, faremos isso usando um loop.
1 function v = criaVetorPasso3 (a ,b , n )
2 h = (b - a ) / n ;
3 v = zeros ( n +1 ,1) ;
4 k = 1; % Neste caso k eh o indice do vetor e i eh o valor
que serah atribuido .
5 for i = a : h : b
6 v(k) = i;
7 k = k + 1;
8 end
Exemplo 8.14 (Média aritmética) Problema: Criar uma function que recebe um
vetor de notas e retorna a média aritmética delas.
Solução: Se notas é o vetor de entrada e m a média então o código pode ser feito
das seguintes formas:
1. Usar um for para fazer um somatório (veja 8.22) das notas e depois dividir pela
quantidade de notas;
Observação 8.2 Apesar de a estrutura for ser uma das principais e mais utilizada nas
implementações, é sempre bom tentar evitá-la quando possível e vetorizar o código. Por
exemplo, se desejamos construir o vetor v = [1 4 9 16 25] poderíamos (além de digitar
manualmente os valores é claro) escrever o seguinte código:
1 v = zeros (5 ,1) ;
2 for i = 1:5
3 v ( i ) = i ^2;
4 end
Exemplo 8.15 (Construir matriz) Problema: Criar uma function que recebe um nú-
mero inteiro positivo n e retorna uma matriz n × n com 2 na diagonal e −1 nas subdiago-
nais10 , isto é:
2 −1 0 0 · · · 0
−1 2 −1 0 · · · 0
A= 0 −1 2 −1 · · · 0
.
.. .. .. .. .. ..
. . . . . .
0 ··· 0 0 −1 2
Antes de mais nada, devemos pré-alocar a matriz A do tamanho correto que ela terá
ao final, isto é, n × n. Para isso, usamos a function zeros pois é o valor predominante.
1 function A = constroiMatriz ( n )
2
3 A = zeros ( n ) ;
4 for i = 1: n
5 for j = 1: n
6 if i == j
7 A (i , j ) = 2;
8 end
9 end
10 end
Resta a parte das subdiagonais. Para isso, só precisamos perceber que o valor −1 ocorre
quando |i − j| == 1. Poderíamos incluir um segundo if dentro dos dois for, assim
(lembre-se que o módulo de um número é calculado pela function abs):
1 function A = constroiMatriz ( n )
2
3 A = zeros ( n ) ;
4 for i = 1: n
5 for j = 1: n
6 if i == j
7 A (i , j ) = 2;
8 end
9 if abs (i - j ) == 1
10 A (i , j ) = -1;
11 end
238 Capítulo 8. MATLAB básico para Cálculo Numérico
12 end
13 end
No entanto, esta não é a forma mais inteligente pois i == j e abs(i-j)== 1 nunca serão
verdadeiras para um mesmo par i,j. Ou seja, se i == j então abs(i-j)~= 1. Assim,
podemos melhorar consideravelmente o código fazendo ele da seguinte forma:
7 if abs (i - j ) == 1
8 A (i , j ) = -1;
9 end
10 end
11 end
Se você ficou confuso com os índices A(i,[i-1, i, i+1]), reveja a seção sobre indexação.
Por fim, a título de curiosidade, o código abaixo mostra como seria possível construir
a matriz sem a necessidade de nenhuma estrutura de repetição e seleção. Ele faz uso do
conceito de indexação sequencial de matriz, que não foi apresentado nesta apostila.
1 function A = constroiMatrizVet ( n )
2 A = zeros ( n ) ;
3 A ((2: n : n *( n -1) ) + (0: n -2) ) = -1;
4 A ((( n +1) : n : n ^2) + (0: n -2) ) = -1;
5 A ((1: n : n ^2) + (0: n -1) ) = 2;
240 Capítulo 8. MATLAB básico para Cálculo Numérico
DICA: Matrizes como as do exemplo acima (com a grande maior parte dos elementos iguais
a zero) são muito comuns em problemas práticos. Elas recebem o nome de matriz esparsa.
O MATLAB possui diversas ferramentas para tratar e manipular de forma adequada este
tipo de matriz e tirar proveito desta estrutura na solução de problemas. Um tratamento
adequado destas matrizes permite resolver problemas que seriam impensáveis sem estas
técnicas.
8.8 Gráficos
Em diversos problemas a visualização de dados e resultados é importante ou
essencial na resolução deles. O MATLAB possui ferramentas que permitem não só gerar
gráficos, mas também editá-los de forma prática.
Dividimos esta seção em gráficos bidimensionais e nos outros formatos. Este primeiro
são os de maior interesse para esta apostila. Já os outros formatos serão apresentados de
forma rápida para curiosidade.
Exemplo 8.16 (Gráfico usando plot) Problema: Criar um script que desenha o grá-
fico da função f (x) = x2 no intervalo [0, 10].
Solução: O gráficos é feito listando um conjunto finito de pontos que serão plotados
na ordem em que aparecem nos vetores. Por padrão, o MATLAB ligará os pontos por
segmentos de reta azuis, mas isso pode ser alterado (veja os próximos exemplos). Precisamos
essencialmente de três passos:
2. Declarar as ordenadas dos pontos (avaliando uma função nas abscissas, por exemplo).
Comando Cor
b azul
g verde
r vermelho
c ciano
m magenta
y Amarelo
k Preto
Tabela 13 – Cores básicas para gráficos.
Solução: Abaixo você pode ver o script e o gráfico que foi gerado.
242 Capítulo 8. MATLAB básico para Cálculo Numérico
1 >> X = - pi :0.1: pi ;
2 >> Y = sin ( X ) ;
3 >> Y2 = cos ( X ) ;
4 >> plot (X , Y )
8.8. Gráficos 243
5 >> plot (X , Y2 )
veremos que apenas o segundo gráfico será exibido e o primeiro será apagado (sobrescrito).
Para fazer isso corretamente, temos duas opções. A primeira é usar a function
plot uma única vez com todos os dados (como descrito na documentação da function). O
código fica:
1 >> plot (X ,Y ,X , Y2 )
ou
1 >> plot (X , Y )
2 >> hold on
3 >> plot (X , Y2 )
1 >> hold on
2 >> plot (X , Y )
3 >> plot (X , Y2 )
• axis: controla a aparência dos eixos. Com ela é possível mudar o intervalo de
visualização da imagem e outras alterações visuais.
244 Capítulo 8. MATLAB básico para Cálculo Numérico
• subplot: permite fazer mais de um gráfico na mesma janela, mas sem estar no
mesmo sistema de eixos.
Exemplo 8.18 Problema: Criar um script que plota a curva parametrizada (cos(t), sen(t), t),
para t ∈ [−2π, 2π].
Solução: Temos
O que faremos é calcular (x(t), y(t), z(t)) em pontos dentro do intervalo dado para
produzir três vetores x, y e z com as coordenadas dos pontos. Assim, o código fica como
abaixo.
8.8. Gráficos 245
Exemplo 8.19 Problema: Criar um script que plota a superfície da função f (x, y) =
cos(x)cos(y) com domínio [−2π, 2π] × [−2π, 2π].
Zij = f (xi , yj ).
246 Capítulo 8. MATLAB básico para Cálculo Numérico
Depois de criar os vetores (de mesmo tamanho) x e y criamos a matriz Z, que deve
ser quadrada. Avaliamos a função nos pontos e armazenamos em Z fazendo dois loops. Em
seguida é só usar a function surf ou mesh.
• Unrecognized function or variable ’A’.: Se A for uma variável do seu código, pro-
vavelmente você programou ele de forma que (na linha indicada) a variável esteja
sendo utilizada antes de ter sido declarada e, portanto, não existe ainda. Verifique se
isso está ocorrendo e refaça seu código. Outra possibilidade é que esta variável não
existe dentro da function na qual ela está sendo utilizada.
• Unrecognized function or variable ’A’.: Se A for uma function ou script, você deve
estar tentando rodar o código de uma pasta diferente de onde ele se encontra.
Verifique o diretório atual (current folder).
• Error using inv Matrix must be square.: Assim como várias outras, a function inv,
possui restrições teóricas de uso. Neste caso, você deve verificar sua implementação
pois está tentando fazer uma conta que não é permitida pela teoria (no caso da inv
o problema foi tentar calcular inversa de uma matriz que não é quadrada).
• Not enough input arguments. e Too many input arguments.: Erros muito comuns de
ocorrerem mas primeiras tentativas de rodar um código. Geralmente ocorre pois o
número de variáveis de entrada fornecido difere da quantia que a function espera. Um
erro muito comum também é tentar rodar (usando F5, por exemplo) uma function.
Neste caso, não estaremos passando nenhuma variável de entrada12 e a function
retornará este erro.
• Matrix dimensions must agree.: Você está tentando fazer uma operação com matrizes
ou vetores que tem dimensões incompatíveis. Por exemplo, somar uma matriz 2 × 2
com outra 3 × 3. Se for dentro de algum código, desmembre a expressão e faça as
variáveis serem exibidas separadamente. Dessa forma, você conseguirá identificar
qual variável está problemática.
11
Formalmente não é uma mensagem de erro e sim um aviso pois o programa tentará usar a pseudoinversa
da matriz.
12
Lembre-se que uma function utiliza um workspace próprio e, por isso, uma variável que está declarada
no workspace do MATLAB não estará disponível para a function.
248 Capítulo 8. MATLAB básico para Cálculo Numérico
• At least one END is missing: the statement may begin here.: Você esqueceu ao menos
um end para uma das estruturas de seleção ou repetição criadas. Alinhe o seu código
(indentação) e verá que um deles está faltando. Tome o cuidado para adicionar na
posição correta ou seu código estará errado novamente.
• Se, ao rodar um código, uma janela como a da figura 28 aparecer significa que
você está tentando rodar um arquivo que está em um diretório diferente do seu
diretório atual (current folder). Se você está ciente disso e realmente quer trocar
de diretório, clique em “Change Folder”. Caso contrário, clique em “Cancelar” e
verifique a localização do arquivo.
The variable ’__’ appears to change size on every loop iteration. Consider
preallocating for speed.
Caso você não faça uso dessa duplicação, o MATLAB irá destacar o operador e
apresentar o seguinte aviso na barra a direita:
When both arguments are numeric scalars, consider replacing & with && for
performance.
Exemplo 8.20 (Hello world) Problema: Criar um script que exibe a frase “Hello
World”.
2 2 Hello World !
Exemplo 8.21 (Máximo e mínimo) Problema: Criar uma function que recebe um
vetor e calcula o maior e menor valor.
Solução: É claro que o MATLAB já possui functions que fazem este cálculo.
A proposta aqui é praticar as estruturas de repetição e seleção, os operadores lógicos e,
principalmente, a capacidade de construir um algoritmo. Existem diversas formas de
organizar este código, aqui iremos apresentar uma das mais básicas.
5 maximo = v (1) ;
6 minimo = v (1) ;
7 for i = 2: n % Percorre as demais componentes do vetor .
8 if v ( i ) > maximo % Caso a componente i de v for maior
que o maximo que jah haviamos encontrado , mudamos o
valor do maximo .
9 maximo = v ( i ) ;
10 end
11 if v ( i ) < minimo % Caso a componente i de v seja menor
que o minimo que jah haviamos encontrado , mudamos o
valor do minimo .
12 minimo = v ( i ) ;
13 end
14 end
Exemplo 8.22 (Somatório) Problema: Criar uma function que recebe um vetor e
soma todas as componentes dele.
Solução: Um dos exemplos mais importantes desta apostila. Como vimos, a func-
tion sum faz este processo, mas podem haver situações nas quais fazer a conta manualmente
8.10. Exemplos clássicos 251
é mais adequada.
A estratégia para fazer essa conta é fazer um laço de repetição para o qual, a cada
passo, um termo a mais é adicionado à variável s. Dentro do for, tomamos o que está
armazenado na variável s e somamos com o termo seguinte v(i). Porém, para que o
primeiro passo seja possível, a variável s precisa existir previamente. Por isso, atribuímos
0 a ela antes deste for. O código resultante fica como abaixo.
Caso você tenha dificuldade em entender este código, podemos inserir um disp
para acompanhar a variável s e suas somas parciais.
252 Capítulo 8. MATLAB básico para Cálculo Numérico
1 function s = somatorio ( v )
2
3 n = length ( v ) ; % Numero de elementos de v .
4
5 s = 0;
6 for i = 1: n
7 s = s + v(i);
8 fprintf ( 'i = %d , % g \ n ' ,i , s )
9 end
É claro que não é necessário que os valores que serão somados estejam alocados em
um vetor. Podemos ter uma fórmula para os termos que desejamos somar. Por exemplo,
para somar o inverso dos números de 1 até n, isto é
n
1
s=
X
,
i=1 i
Exemplo 8.23 (Sorting) Problema: Criar uma function que recebe um vetor e ordena
os números em ordem crescente.
1 function v = sorting ( v )
2
3 n = length ( v ) ;
4
5 for i = 2: n
6 j = i;
7 while j > 1 && v (j -1) > v ( j )
8 v ([ j , j -1]) = v ([ j -1 , j ]) ;
9 j = j - 1;
10 end
11 end
A ideia básica deste algoritmo é percorrer cada um dos elementos do vetor e, para
cada um deles, procurar a posição dele entre os anteriores fazendo trocas de posições. A
título de curiosidade, para vetores de 104 elementos, a function sort pode chegar mais de
10mil vezes mais rápido que o algoritmo acima.
Exemplo 8.24 (Máximo entre 3 números) Problema: Criar uma function que re-
cebe três números e retorna o maior deles.
7 else
8 m = c;
9 end
Exemplo 8.25 (Multiplicação matriz-vetor) Problema: Criar uma function que re-
cebe uma matriz A ∈ Rm×n e um vetor x ∈ Rn e calcula y = Ax.
8.10. Exemplos clássicos 255
Solução: Antes de mais nada, é claro que esta operação já é possível diretamente
pela operação de multiplicação ∗. Porém, este é um bom exercício para desenvolver a
capacidade de construir algoritmos, entender as operações com matrizes e o conceito de
vetorização.
O primeiro passo para construir o código é entender como a conta é realizada. Note
que, para a primeira linha da matriz A fazemos:
n
y1 = a11 x1 + a12 x2 + . . . a1n xn = (8.1)
X
a1j xj
j=1
1 for i = 1: m
2 y ( i ) = A (i ,:) * x ;
3 end
256 Capítulo 8. MATLAB básico para Cálculo Numérico
Solução: A ideia básica para este código é o exemplo 8.25. O que precisamos fazer
é repetir o que foi feito lá para cada uma das colunas da matriz B. Para cada linha i da
matriz A, multiplicamos ela por cada coluna de B (correspondente ao vetor x no exemplo
8.25). Para cada coluna de B precisamos fazer um somatório. Assim, a expressão que será
implementada é:
n
Cij = ai1 b1j + ai2 b2j + . . . ain bnj =
X
aik bkj
k=1
Exemplo 8.27 (Adição de matrizes) Problema: Criar uma function que recebe duas
matrizes A e B de mesmo tamanho e calcula C = A + B elemento por elemento.
Solução: Assim como fazemos algebricamente, a ideia aqui é percorrer cada linha
e cada coluna e somar os elementos correspondentes. Como sabemos quantas linhas e
colunas iremos percorrer, utilizaremos dois for, um para cada linha e outro pra percorrer
cada coluna de uma linha dada (escrever a frase desta forma é importante para percebermos
a estrutura que o código de tomar). Abaixo temos duas versões similares do mesmo código,
diferindo apenas como lidamos com as dimensões das matrizes.
9
10 C = zeros (m , n ) ; % Pre - alocamos a memoria para a variavel C
para que nao seja necessario mudanca no tamanho dela .
11 for i = 1: m % Para cada linha da matriz .
12 for j = 1: n % Para cada coluna da matriz .
13 C (i , j ) = A (i , j ) + B (i , j ) ;
14 end
15 end
Exemplo 8.28 (Números primos) Problema: Criar uma function que recebe um nú-
mero n ≥ 2 inteiro e diz se ele é primo13 ou não.
Solução: Primeiramente, vamos definir que a saída da function será uma flag14 ,
isto é, ela irá retornar 0 caso o número não seja primo e 1 caso seja.
13
Relembrando: um número inteiro é dito primo se seus únicos divisores são 1 e ele mesmo.
14
Apesar da tradução literal ser “bandeira”, um termo mais adequado neste caso seria “indicador” ou
“marcador”
8.10. Exemplos clássicos 259
A teoria matemática vem muito a calhar quando estamos programando pois fornece
diversos recursos teóricos que podemos auxiliar em deixar o código mais eficiente. Nesta
caso, utilizaremos um resultado muito simples da Teoria dos Números: para verificar se
√
um número n é primo basta testar os divisores até n. Facilmente percebemos como esse
resultado reduz consideravelmente o número de testes (para n = 101 precisávamos de 99
testes e agora precisamos de 8). A function isprime4 abaixo implementa esta alteração.
4 if n < 2 || n ~= round ( n )
5 disp ( 'O numero precisa ser inteiro e maior que 1 ') ;
6 flag = 0;
7 else
8 flag = 1;
9 for i = 2: floor ( sqrt ( n ) )
10 a = n/i;
11 if a == round ( a )
12 flag = 0;
13 break % Interrompe o FOR .
14 end
15 end
16 end
DICA: Você pode verificar que os códigos apresentados aqui dão a resposta desejada
comparando com a function isprime.
Exemplo 8.29 (Unicidade) Problema: Criar uma function que recebe um vetor e
retira as componentes repetidas retornando um vetor sem repetições.
Vamos fazer uma busca por todos as demais componentes de v nos perguntando:
“v(i) já está em v2?”. Por causa disso iremos usar um for indo da segunda componente
de v até a última.
Para cada i fazemos uma busca em v2 para ver se v(i) está em v2. Para isso,
utilizaremos um while pois não sabemos quando iremos parar 15
. A variável flag serve
para indicar se já encontramos v(i) em v2 ou não (flag == 1 significa que ainda não e
flag == 0 significa que encontrou). Por isso, o while recebe a condição dada.
Além disso, não podemos exceder a dimensão de v2 então limitamos o índice k para
no máximo j-1. A variável j denota a posição na qual o novo valor único será inserido
15
Poderíamos usar um for junto com um break também.
262 Capítulo 8. MATLAB básico para Cálculo Numérico
Caso a busca do while retorne mal sucedida (ou seja, não achou v(i) em v2) a
variável flag terá permanecido com o valor 1. Neste caso, o valor de v(i) é incluído em
v2 e passamos para o próximo valor de i.
DICA: Como é esperado, o MATLAB possui uma function que faz a unicidade das
componentes de um vetor (ou matriz). Esta function chama-se unique.
8.10. Exemplos clássicos 263
Exemplo 8.30 (Fatorial) Problema: Criar uma function que recebe um número inteiro
positivo e retorna o fatorial dele.
n! = 1 · 2 · 3 · · · · · n.
Assim,o código pode ser feito como abaixo. Uma mensagem para o caso em que n
seja negativo ou não inteiro foi incluída também.
Exemplo 8.31 (Área do círculo) Problema: Criar uma function que um número r >
0 e retorna a área do círculo de raio r.
1 function a = areacirculo2 ( r )
2
3 if r <= 0
4 disp ( 'O raio deve ser um numero positivo . ')
5 a = NaN ;
6 else
7 a = pi * r ^2;
8 end
Referências