Você está na página 1de 269

Prof.

Edson Luiz Valmorbida

Apostila de Cálculo Numérico


- versão 2 -

Londrina

2020
Lista de implementações

2.1 Método da bisseção. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42


2.2 Método de Newton. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
2.3 Método da secante. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.1 Método de Jacobi escalar - primeira forma. . . . . . . . . . . . . . . . . . . 67
3.2 Método de Jacobi escalar - segunda forma. . . . . . . . . . . . . . . . . . . 69
3.3 Método de Jacobi escalar - terceira forma. . . . . . . . . . . . . . . . . . . 70
3.4 Método de Jacobi matricial. . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.5 Método de Gauss-Seidel escalar - primeira forma. . . . . . . . . . . . . . . 75
3.6 Método de Gauss-Seidel matricial. . . . . . . . . . . . . . . . . . . . . . . . 76
4.1 Forma de Lagrange para interpolação. . . . . . . . . . . . . . . . . . . . . . 91
4.2 Forma de Newton para interpolação. . . . . . . . . . . . . . . . . . . . . . 101
4.3 Forma de Newton-Gregory para interpolação. . . . . . . . . . . . . . . . . 106
5.1 Método dos mínimos quadrados - primeira forma. . . . . . . . . . . . . . . 121
5.2 Método dos mínimos quadrados - primeira forma (usando sum). . . . . . . 122
5.3 Método dos mínimos quadrados - segunda forma. . . . . . . . . . . . . . . 123
6.1 Regra dos trapézios - primeira forma. . . . . . . . . . . . . . . . . . . . . . 132
6.2 Regra dos trapézios - segunda forma. . . . . . . . . . . . . . . . . . . . . . 133
6.3 Regra dos trapézios - terceira forma. . . . . . . . . . . . . . . . . . . . . . 134
6.4 Regra dos trapézios - quarta forma. . . . . . . . . . . . . . . . . . . . . . . 135
6.5 Regra dos trapézios - forma vetorizada. . . . . . . . . . . . . . . . . . . . . 136
6.6 Regra de Simpson 1/3 - primeira forma. . . . . . . . . . . . . . . . . . . . 142
6.7 Regra de Simpson 1/3 - segunda forma. . . . . . . . . . . . . . . . . . . . . 143
6.8 Regra de Simpson 1/3 - terceira forma. . . . . . . . . . . . . . . . . . . . . 144
6.9 Regra de Simpson 1/3 - quinta forma. . . . . . . . . . . . . . . . . . . . . . 145
6.10 Regra de Simpson 1/3 - forma vetorizada. . . . . . . . . . . . . . . . . . . 146
7.1 Método de Euler. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
7.2 Método de Runge-Kutta de 2a ordem. . . . . . . . . . . . . . . . . . . . . . 159
7.3 Método de Runge-Kutta de 4a ordem. . . . . . . . . . . . . . . . . . . . . . 163
8.1 Exemplo de como resolver um sistema linear. . . . . . . . . . . . . . . . . . 183
8.2 Function para trocar elementos de um vetor de posição - versão 1. . . . . . 202
8.3 Function para trocar elementos de um vetor de posição - versão 2. . . . . . 202
8.4 Exemplo de function para calcular norma de vetor. . . . . . . . . . . . . . 204
8.5 Exemplo script para testar function. . . . . . . . . . . . . . . . . . . . . . 220
8.6 Exemplo par ou ímpar com if. . . . . . . . . . . . . . . . . . . . . . . . . 228
8.7 Exemplo contador com while. . . . . . . . . . . . . . . . . . . . . . . . . . 231
8.8 Exemplo divisão por 2 com while. . . . . . . . . . . . . . . . . . . . . . . 232
8.9 Exemplo vetor de passo com for - versão 1. . . . . . . . . . . . . . . . . . 234
8.10 Exemplo vetor de passo com for - versão 2. . . . . . . . . . . . . . . . . . 234
8.11 Exemplo vetor de passo com for - versão 3. . . . . . . . . . . . . . . . . . 234
8.12 Exemplo média aritmética - versão 1. . . . . . . . . . . . . . . . . . . . . . 235
8.13 Exemplo média aritmética - versão 2. . . . . . . . . . . . . . . . . . . . . . 235
8.14 Exemplo de construção de matriz - versão 0. . . . . . . . . . . . . . . . . . 238
8.15 Exemplo de construção de matriz - versão 1. . . . . . . . . . . . . . . . . . 238
8.16 Exemplo de construção de matriz - versão 2. . . . . . . . . . . . . . . . . . 239
8.17 Exemplo de gráfico 2D com plot. . . . . . . . . . . . . . . . . . . . . . . . 241
8.18 Exemplo de mudança no estilo de um gráfico. . . . . . . . . . . . . . . . . 242
8.19 Exemplo de dois gráficos em uma única figura. . . . . . . . . . . . . . . . . 243
8.20 Exemplo curva no espaço com plot3. . . . . . . . . . . . . . . . . . . . . . 245
8.21 Exemplo superfície 3D com surf. . . . . . . . . . . . . . . . . . . . . . . . . 246
8.22 Script Hello World. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
8.23 Function para máximo e mínimo de vetor. . . . . . . . . . . . . . . . . . . 249
8.24 Function para somar componentes de um vetor - versão 1. . . . . . . . . . 251
8.25 Function para ordenação de valores. . . . . . . . . . . . . . . . . . . . . . . 252
8.26 Function para máximo entre 3 valores - versão 1. . . . . . . . . . . . . . . 253
8.27 Function para máximo entre 3 valores - versão 2. . . . . . . . . . . . . . . 254
8.28 Function para máximo entre 3 valores - versão 3. . . . . . . . . . . . . . . 254
8.29 Function para produto matriz-vetor. . . . . . . . . . . . . . . . . . . . . . 255
8.30 Function para produto de matrizes - versão escalar. . . . . . . . . . . . . . 256
8.31 Function para produto de matrizes - versão vetorizada. . . . . . . . . . . . 257
8.32 Function para soma de matrizes - versão 1. . . . . . . . . . . . . . . . . . . 257
8.33 Function para soma de matrizes - versão 2. . . . . . . . . . . . . . . . . . . 258
8.34 Function para número primo - versão 2. . . . . . . . . . . . . . . . . . . . . 259
8.35 Function para número primo - versão 3. . . . . . . . . . . . . . . . . . . . . 259
8.36 Function para número primo - versão 4. . . . . . . . . . . . . . . . . . . . . 260
8.37 Function unicidade de valores de um vetor. . . . . . . . . . . . . . . . . . . 262
8.38 Function para fatorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
8.39 Function para fatorial - versão recursiva. . . . . . . . . . . . . . . . . . . . 264
8.40 Function para área de círculo - versão 1. . . . . . . . . . . . . . . . . . . . 264
8.41 Function para área de círculo - versão 2. . . . . . . . . . . . . . . . . . . . 264
Lista de métodos

2.1 Método da bisseção . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37


2.2 Método de Newton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
2.3 Método da secante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.2 Método de Jacobi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.3 Método de Jacobi matricial . . . . . . . . . . . . . . . . . . . . . . . . 65
3.4 Método de Gauss-Seidel . . . . . . . . . . . . . . . . . . . . . . . . . . 73
3.5 Método de Gauss-Seidel matricial . . . . . . . . . . . . . . . . . . . . . 75
4.2 Polinômio interpolador na forma de Lagrange . . . . . . . . . . . . . . 88
4.4 Polinômio interpolador na forma de Newton . . . . . . . . . . . . . . . 97
4.6 Polinômio interpolador na forma de Newton-Gregory . . . . . . . . . . 104
5.2 Método dos mínimos quadrados . . . . . . . . . . . . . . . . . . . . . . 116
6.2 Regra dos trapézios generalizada . . . . . . . . . . . . . . . . . . . . . 130
6.4 Regra de Simpson 1/3 generalizada . . . . . . . . . . . . . . . . . . . . 140
7.2 Método de Euler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
7.3 Método de Runge-Kutta de segunda ordem . . . . . . . . . . . . . . . . 157
7.4 Método de Runge-Kutta de quarta ordem . . . . . . . . . . . . . . . . 160
Lista de ilustrações

Figura 1 – Estrutura geral de um problema numérico. . . . . . . . . . . . . . . . . 17


Figura 2 – Função real com 3 raízes reais. . . . . . . . . . . . . . . . . . . . . . . . 32
Figura 3 – Estrutura geral de um método iterativo. . . . . . . . . . . . . . . . . . 33
Figura 4 – Gráfico de funções satisfazendo as hipóteses do TVI. . . . . . . . . . . 35
Figura 5 – Primeira iteração do método da bisseção. . . . . . . . . . . . . . . . . . 36
Figura 6 – Gráfico de uma função f e da aproximação linear L0 . . . . . . . . . . . 44
Figura 7 – Aproximação x1 obtida a partir da reta y = L0 (x). . . . . . . . . . . . 44
Figura 8 – Gráfico de uma função f e da aproximação linear L1 . . . . . . . . . . . 45
Figura 9 – Decomposição da matriz A para a forma matricial do método. . . . . . 64
Figura 10 – Esboço da interpolação de f por g. . . . . . . . . . . . . . . . . . . . . 82
Figura 11 – Um interpolador não descreve bem os dados neste caso. . . . . . . . . . 113
Figura 12 – Dados e modelo para o exemplo 5.1. . . . . . . . . . . . . . . . . . . . 118
Figura 13 – Soma de Riemann usando interpolador de grau 0. . . . . . . . . . . . . 128
Figura 14 – Visualização da regra do trapézio simples. . . . . . . . . . . . . . . . . 129
Figura 15 – Visualização da regra dos trapézios generalizada. . . . . . . . . . . . . 130
Figura 16 – Esboço do interpolador de grau 2 para a forma de Simpson. . . . . . . 138
Figura 17 – Algumas das empresas e instituições que utilizam o MATLAB no Brasil.
Fonte: <https://opencadd.com.br/>. . . . . . . . . . . . . . . . . . . . 170
Figura 18 – Layout básico do MATLAB. . . . . . . . . . . . . . . . . . . . . . . . . 173
Figura 19 – Recursos adicionais do MATLAB. . . . . . . . . . . . . . . . . . . . . . 175
Figura 20 – Editor do MATLAB. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
Figura 21 – Fluxograma da execução de uma function. . . . . . . . . . . . . . . . . 197
Figura 22 – Estrutura geral das implementações feitas na apostila. . . . . . . . . . 199
Figura 23 – Teste do script para a function operacoes. . . . . . . . . . . . . . . . 200
Figura 24 – Teste do script com múltiplos usos da function operacoes. . . . . . . . 200
Figura 25 – Teste do script para a function det2x2. . . . . . . . . . . . . . . . . . 201
Figura 26 – Declaração de variáveis de texto. . . . . . . . . . . . . . . . . . . . . . 217
Figura 27 – Utilização das aspas duplas no disp. . . . . . . . . . . . . . . . . . . . 219
Figura 28 – Mensagem de aviso sobre o diretório atual no MATLAB. . . . . . . . . 248
Lista de tabelas

Tabela 1 – Resumo das iterações do método da bisseção. . . . . . . . . . . . . . . 40


Tabela 2 – Resumo das iterações do método de Newton. . . . . . . . . . . . . . . 46
Tabela 3 – Resumo das iterações do método da secante. . . . . . . . . . . . . . . . 50
Tabela 4 – Diagrama da mudança das variáveis no método da secante. . . . . . . . 52
Tabela 5 – Organização da tabela de diferenças divididas. . . . . . . . . . . . . . . 93
Tabela 6 – Lista de formatos básicos de exibição. . . . . . . . . . . . . . . . . . . 179
Tabela 7 – Operações básicas para matrizes e vetores. . . . . . . . . . . . . . . . . 182
Tabela 8 – Funções de arrendondamento. . . . . . . . . . . . . . . . . . . . . . . . 213
Tabela 9 – Funções trigonométricas. . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Tabela 10 – Lista de operadores lógicos básicos. . . . . . . . . . . . . . . . . . . . . 221
Tabela 11 – Lista de operadores lógicos de combinação. . . . . . . . . . . . . . . . . 223
Tabela 12 – Resumo dos casos para E e OU. . . . . . . . . . . . . . . . . . . . . . . 224
Tabela 13 – Cores básicas para gráficos. . . . . . . . . . . . . . . . . . . . . . . . . 241
Tabela 14 – Tipos de marcadores para gráficos. . . . . . . . . . . . . . . . . . . . . 242
Tabela 15 – Tipos de traços para gráficos. . . . . . . . . . . . . . . . . . . . . . . . 242
Sumário

1 NOÇÕES BÁSICAS SOBRE ERROS . . . . . . . . . . . . . . . . . 17


1.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.2 Sistemas de Numeração e Conversão entre Base . . . . . . . . . . . 19
1.2.1 Binário→Decimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.2.2 Decimal→Binário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.3 Sistema de Ponto Flutuante . . . . . . . . . . . . . . . . . . . . . . . 24
1.4 Efeitos numéricos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.5 Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

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

5 AJUSTE DE CURVAS . . . . . . . . . . . . . . . . . . . . . . . . . 113


5.1 Método dos Mínimos Quadrados . . . . . . . . . . . . . . . . . . . . . 114
5.2 Caso Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
5.3 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
5.3.1 Primeira forma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
5.3.2 Segunda forma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
5.3.3 Basic Fitting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
5.4 Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

6 INTEGRAÇÃO NUMÉRICA . . . . . . . . . . . . . . . . . . . . . . 127


6.1 Regra dos Trapézios . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
6.1.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
6.2 Regra 1/3 de Simpson . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
6.2.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
6.3 Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

7 EQUAÇÕES DIFERENCIAIS ORDINÁRIAS . . . . . . . . . . . . . 151


7.1 Método de Euler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
7.1.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
7.2 Método de Runge-Kutta de 2ª ordem . . . . . . . . . . . . . . . . . . 156
7.2.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
7.3 Método de Runge-Kutta de 4ª ordem . . . . . . . . . . . . . . . . . . 160
7.3.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
7.4 Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

8 MATLAB BÁSICO PARA CÁLCULO NUMÉRICO . . . . . . . . . . 169


8.1 Sobre o MATLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
8.1.1 Instalação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
8.2 Aspectos Gerais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
8.2.1 Comandos Iniciais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
8.2.2 Nome de Variáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
8.2.3 Variáveis predefinidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
8.2.4 Formatos de exibição . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
8.3 Matrizes e Vetores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
8.3.1 Solução de Sistemas Lineares . . . . . . . . . . . . . . . . . . . . . . . . . 183
8.3.2 Indexação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
8.4 Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
8.4.1 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
8.4.2 Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
8.4.2.1 input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
8.4.3 Dois exemplos simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
8.5 Funções Básicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
8.5.1 Polinômios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
8.5.2 Funções de arrendondamento . . . . . . . . . . . . . . . . . . . . . . . . . 213
8.5.3 Funções anônimas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
8.5.4 Funções Matemáticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
8.6 Variáveis de texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
8.7 Estruturas de seleção e repetição . . . . . . . . . . . . . . . . . . . . 221
8.7.1 Lógica Booleana . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
8.7.2 if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
8.7.3 switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
8.7.4 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
8.7.5 for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
8.8 Gráficos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
8.8.1 Gráficos Bidimensionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
8.8.2 Gráficos Tridimensionais . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
8.9 Mensagens de erro comuns . . . . . . . . . . . . . . . . . . . . . . . . 246
8.10 Exemplos clássicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
REFERÊNCIAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
15

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

1 Noções Básicas Sobre Erros

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.

Neste capítulo veremos um pouco sobre como os computadores funcionam, como


isso difere da forma como estamos acostumados a pensar e, principalmente, quais problemas
podem surgir em decorrência disso.

1.1 Introdução

A figura 1 mostra a estrutura geral de um problema prático de forma simplificada


(retirada de [1]).

Figura 1 – Estrutura geral de um problema numérico.


18 Capítulo 1. Noções Básicas Sobre Erros

Primeiramente, tendo em mãos um problema real de qualquer natureza, utilizamos


dados conhecidos para criar um modelo matemático que descreve o problema de alguma
forma. Neste ponto ocorre o que chamamos de erro de modelagem, isto é, o erro que
cometemos ao tentar descrever um fenômeno de forma simplificada através de equações
fazendo suposições que não condizem totalmente com a realidade (desconsiderar a força de
atrito ou o efeito da gravidade, por exemplo). Por um lado, aumentar o erro de modelagem
implica em uma solução que assemelha-se menos com a realidade do fenômeno descrito.
Por outro lado, diminuir o erro de modelagem implica em aumentar a complexidade do
problema, o que torna necessário mais recursos computacionais e de tratamentos teóricos.
Saber balancear a complexidade do problema com os recursos disponíveis é essencial para
obter a melhor solução possível.

Tendo em mãos um modelo matemático, podemos optar entre solucioná-lo anali-


ticamente (como os métodos vistos costumeiramente num curso de EDO, por exemplo)
obtendo a solução exata do problema ou numericamente encontrando uma aproximação da
solução do problema. Esta segunda abordagem é o tema desta apostila e será tratada nos
próximos capítulos. Por serem aproximações, estas soluções resultam no que chamamos
de erros de representação, isto é, o erro que cometemos ao aproximar a solução de um
problema matemático.

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.

A partir do método numérico escolhido realizamos a implementação computacional


dele (caso ela ainda não esteja disponível) e do problema que será resolvido (definir dados,
parâmetros, etc). Note que aqui não cogitamos a possibilidade de calcular a solução pelo
método escolhido fazendo contas “manualmente”. Isso se deve ao fato que são raros os
casos na atualidade onde é possível fazer estes cálculos.

IMPORTANTE: Nesta apostila os exemplos com contas manuais serão apre-


sentados apenas com o intuito de entendimento do procedimento dos métodos
e estruturação dos algoritmos.
1.2. Sistemas de Numeração e Conversão entre Base 19

Em decorrência desta implementação computacional e da forma como os compu-


tadores realizam as contas surgem o terceiro tipo de erro neste processo que é chamado
de erro de implementação1 e surge pela aritmética finita como os sistema computacionais
operam.

A implementação computacional, após ser executada, retornará uma aproximação


para solução do problema real inicial. Esta solução aproximada pode estar dentro do
esperado ou não dependendo do erro acumulado pelos três erros descritos acima. Caso
pelo menos um deles seja significante poderá gerar uma resposta que não condiz com o
esperado ou até mesmo que seria possível. Com isso, precisamos analisar estes resultados
e, na medida do possível, alterar o processo de modo a reduzir os erros.

DICA: Geralmente, reduzir o erro de representação é a primeira tentativa pois tem um


custo/esforço inferior aos demais. Para isso, revisamos o problema para mudar o método
utilizado na aproximação. Se isso não for possível ou eficaz, podemos revisar o modelo
adicionando, removendo ou corrigindo o que for possível e necessário. Como último recurso,
podemos mudar para um sistema computacional de maior precisãoa . Porém, esta última
opção costuma gerar custos muito altos ou simplesmente não ser possível.
a
Os sistemas computacionais pessoais atuais costumam ser ao menos equivalente, sendo necessário
utilizar um supercomputador ou semelhante. Por isso, “mudar de computador” não irá melhorar a
solução.

Nesta apostila focaremos em estudar diferentes métodos para 6 tipos de problemas


e suas implementações computacionais. Não faremos o processo de modelagem (comum
em cursos de física básica) e veremos apenas alguns apontamentos a respeito da análise
dos resultados.

1.2 Sistemas de Numeração e Conversão entre Base

Um sistema de numeração é um procedimento em que um conjunto de números são


representados por numerais de uma forma consistente. Em outras palavras, um sistema
de numeração é qualquer forma de representar quantidades através símbolos (algarismos,
desenhos, etc).

1
Que não é o erro cometido ao escrever um código.
20 Capítulo 1. Noções Básicas Sobre Erros

Ao longo da história houveram diversas formas de representar os números, algumas


usadas até hoje:

• Sistema Decimal: é o principal sistema utilizado no mundo atual. Como o próprio


nome diz, faz uso de 10 algarismos.

• 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 Sexagesimal: utiliza 60 algarismos. Tem origem na antiguidade e hoje é


utilizada principalmente para contagem de tempo e ângulos.

• 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:

6572 = 2 × 100 + 7 × 101 + 5 × 102 + 6 × 103 .

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:

0, 125 = 1 × 10−1 + 2 × 10−2 + 5 × 10−3 .

1.2.1 Binário→Decimal

Um número representado em binário (base 2) possui dígitos 0 ou 1 listados na


mesma ordem que na base decimal, isto é, a direita antes da vírgula está a unidade e indo
para a esquerda temos a “dezena”, “centena”, etc. Para convertermos um número que está
na base 2 para a sua representação na base 10 basta multiplicarmos cada dígito pelas
potências de 2 correspondentes.
1.2. Sistemas de Numeração e Conversão entre Base 21

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.

Portanto, 100011(2) na base 10 é 35(10) .

Seguindo o mesmo raciocínio, quando temos termos não-inteiros utilizamos potências


negativas para os dígitos à direita da vírgula.

Exemplo 1.2 Considere o número (110, 1011)(2) . Convertendo para a base 10 obtemos:

1 × 22 + 1 × 21 + 0 × 20 + 1 × 2−1 + 0 × 2−2 + 1 × 2−3 + 1 × 2−4 =

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

O processo inverso ao mostrado na seção anterior é feito invertendo as operações.


Se possuímos um número na base 10 e queremos convertê-lo para a base 2 precisamos
dividir (ao invés de multiplicar) pela base.

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

Outro modo comum de fazer a conta do exemplo exemplo anterior é utilizando as


potências de 2. Seguimos a seguinte rotina:

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.

2. Repetimos o processo com a diferença entre a potência de 2 do passo anterior e


número. Neste caso, 25 − 16 = 9 e a nova potência é 23 .

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

e a representação é dada pelos algarismos que multiplicam as potências de 2, isto é,


25(10) = 11001(2) .

Para os números fracionários, o processo se resume da seguinte forma:

• Multiplicar a parte fracionária por 2;

• 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

Assim, 0, 1875 = 0, 0011(2) . Podemos verificar que a resposta convertendo o número


encontrado de volta para a base 10.

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.

Exemplo 1.5 Vamos escrever o número 0, 6 na base 2. Seguindo os passos indicados


temos:

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) .

IMPORTANTE: Por causa de situações como a do exemplo anterior teremos problemas


decorrentes da representação numérica no computador. Simplesmente, computadores não
conseguem armazenar dízimas periódicas pois tem uma quantidade finita de espaço.
24 Capítulo 1. Noções Básicas Sobre Erros

1.3 Sistema de Ponto Flutuante


O sistema de ponto flutuante é uma arquitetura computacional adotada para
representar os dados numéricos. A ideia base deste sistema é usar o deslocamento da
vírgula (que na notação em inglês é um ponto, por isso “ponto flutuante” ou floating point)
deixando na notação científica na base 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) .

No sistema de ponto flutuante, um número real será representado na forma (seguindo


o padrão IEEE 754):

0, d1 d2 . . . dj ×β e
| {z }
M antissa

onde:

• β é a base em que o sistema opera;

• j é o número de dígitos da mantissa;

• 0 ≤ dj ≤ β − 1 são os dígitos do sistema de numeração e d1 6= 0;

• e é o expoente da base, tal que emin ≤ e ≤ emax .

Sendo assim, um sistema de ponto flutuante depende do tamanho da mantissa


disponível, da base utilizada (2 no nosso caso) e dos expoentes máximo e mínimo permitidos.

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) .

Tradicionalmente, um número em ponto flutuante é representado em uma “fita” de


algarismo para melhor visualização. Se o sistema de ponto flutuante escolhido é tal que
β = 2, j = 10 e −15 ≤ e ≤ 15 então escrevemos o número como

Em resumo, em uma máquina de 16 bits2 utilizamos:


2
Isto é, que usa 16 bits para armazenar um número
1.3. Sistema de Ponto Flutuante 25

• O primeiro espaço para representar o sinal do número (positivo = 0 ou negativo


= 1).

• 10 espaços para guardar a mantissa.

• Um espaço para o sinal do expoente (lembre-se que na notação científica o expoente


pode ser positivo ou negativo dependendo para qual lado movemos a vírgula).

• 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

1.4 Efeitos numéricos


Por causa dos problema apresentados na seção anterior surgem o que chamamos
de erros de implementação. Estes causam diversos efeitos que não são vistos na aritmética
exata. O cuidado e tratamento destes efeitos numéricos requerem uma atenção refinada
muito além da proposta desta disciplina. No entanto, nesta seção veremos alguns problemas
causados pelos erros de implementação e como eles pode ser significantes na solução final
de um problema prático.

• Cancelamento: Dois números muito próximos, porém diferentes, podem se can-


celarem caso sejam subtraídos pois possuem a mesma representação no sistema
utilizado.

• Propagação de erro: Se uma operação é realizada diversas vezes e um erro de


precisão é carregado e acumulado pode ocorrer que a soma final seja significativamente
diferente do valor correto que seria obtido em aritmética exata.

• Instabilidade numérica: Ocorre quando erros intermediários em uma conta influ-


encia o resultado final de forma significativa. De modo geral, desejamos algoritmos
estáveis pois são menos suscetíveis a estas instabilidades.

• Mal condicionamento: Quando pequenas alterações nas informações iniciais de


um algoritmo (ou qualquer conjunto de passos) influenciam significantemente no
resultado final chamamos este problema de mal posto. Neste caso, soluções indesejadas
são obtidas em decorrência de problemas no modelo utilizado.

A seguir citamos alguns exemplos onde os efeitos numéricos podem ser percebidos.

Exemplo 1.7 Considere os seguintes sistemas lineares:


 

 x+y =2 
 x+y =2
x + 1.001y = 2.001 x + 1.001y = 2.002

 

Podemos verificar facilmente que a solução do primeiro sistema é x = 1 e y = 1.


No entanto, se por algum problema de medição ou de imprecisões em cálculos prévios
obtivermos o segundo sistema ao invés do primeiro (com uma perturbação da ordem de
10−3 em um dos coeficiente) a solução exata do sistema muda para x = 0 e y = 2. Este é
1.4. Efeitos numéricos 27

um exemplo de mal condicionamento ou instabilidade numérica (caso faça parte de um


processo maior).

Exemplo 1.8 Considere a EDO:



y 00 =y








 y(0) = a



y 0 (0) = b.


para constantes a e b dadas.

Sabemos da teoria de EDO que a solução geral deste problema é y = c1 ex + c2 e−x .


Se a = 1 e b = −1 então vemos que c1 = 0 e c2 = 1 e, portanto y = e−x .

No entanto, se a = 1 e b = −1 + δ, para algum valor


! δ pequeno, então vemos que
δ x δ −x
c1 = δ/2 e c2 = 1 − δ/2 e a solução é y = e + 1 − e .
2 2
Até este ponto tudo está de acordo com a teoria das equações diferenciais. Porém,
se δ é algum erro/perturbação nos dados do problema então podemos ver o impacto disto
na solução. Enquanto o primeiro par de condições iniciais gera uma solução que converge
para 0 quando x vai para +∞, o segundo par gera uma solução que diverge quando x → ∞.
Isso muda completamente não só a solução, mas a interpretação do fenômeno que a EDO
descreve.

Exemplo 1.9 O site <http:// www-users.math.umn.edu/ ~arnold/ disasters/ > apresenta


3 casos nos quais erros numéricos causaram desastres.
28 Capítulo 1. Noções Básicas Sobre Erros

1.5 Exercícios

1. Converta os números abaixo para o sistema binário.


a) 129 d) 0, 6 g) 0, 138

b) 281 e) 21, 4 h) 45, 128

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) .

2. Converta os números abaixo para o sistema decimal.


a) 1110011(2) c) 100001, 101(2) e) 0, 01001(2)

b) 11011, 1(2) d) 10, 0111(2) f) 111011(2)


Resposta: a) 230; b) 27, 5; c) 33, 625.

3. Implemente um código que converte um número da base 2 para a base 10.


DICA: Uma das partes mais difíceis desta questão é separar os dígitos de um
número.

4. Implemente um código que converte um número da base 10 para a base 2.


DICA: Use as functions dec2bin e bin2dec para conferir o código feito nestas duas
questões.

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 .

Implemente uma function no MATLAB que recebe n e x e calcula a soma parcial


da série. Implemente também um script que testa esta function e calcula o erro em
relação a function exp (módulo da diferença entre os valores). Descubra quantos
termos são necessários para obter um erro menor que 10−8 para x = 5.

6. Considere o sistema linear 


0.005 x + y = 0.5

x+y =1


Resolva-o analiticamente via escalonamento usando 3 dígitos significativos e compare


com a solução exata (use o MATLAB para obtê-la).
1.5. Exercícios 29

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.

Outras duas interpretações importantes equivalentes deste problema são “encontrar


as soluções de uma equação não-linear f (x) = 0” e “determinar o conjunto de nível
f (x) = 0 de uma função f ”. Estas diferentes interpretações são importantes pois levam à
outras formas de atacar o problema e, por consequência, novos métodos. Em particular,
olhar como uma equação não-linear é muito útil quando o problema para funções de Rn
em Rn são abordados1 .

Na prática, estaremos interessados e será suficiente que encontremos uma aproxi-


mação para ao menos uma das raízes. Sendo assim, neste capítulo trataremos do problema:

“Dada uma função f , encontrar uma aproximação para uma das


soluções reais da equação f (x) = 0, caso ela exista.”

Observação 2.1 A partir deste ponto iremos assumir que a função analisada é contínua.

Definição 2.1 Um número real a é um zero da função f ou raiz da equação f (x) = 0 se


f (a) = 0.

Exemplo 2.1 Na figura 2, os zeros da função são −1, 1 e 3.

Algumas soluções particulares para o problema deste capítulo já são conhecidas.


Por exemplo,

• Se f (x) = ax + b, a 6= 0, então f tem uma única raiz e é igual a x = −b/a.


1
Diversos problemas relacionados a maximização e minimização resultam em sistemas não-lineares, isto
é, um sistema com várias incógnitas mas com equações que não são planos no espaço.
32 Capítulo 2. Zeros de Funções

Figura 2 – Função real com 3 raízes reais.

• 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.

• Para polinômios de grau 3, f (x) = ax3 + bx2 + cx + d = 0, o método de Cardano


pode ser utilizado.

No entanto, este conjunto de soluções conhecida é muito pequeno e restrito. De


fato, no caso de polinômios de grau mais alto e no caso de funções mais complicadas, pode
ser impossível achar os zeros exatamente. Por isso, temos que nos contentar em encontrar
apenas aproximações para esses zeros.

IMPORTANTE: Os métodos que iremos estudar consistem em encontrar uma aproxi-


mação para um dos zeros de uma função com uma precisão prefixada. A ideia principal
desses métodos é partir de uma aproximação inicial para a raiz e em seguida refinar esta
aproximação através de um processo iterativo. A figura 3 esboço a estrutura geral dos
métodos que estudaremos.

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

problemas aplicados), através de um método de convergência global ou através de algum


método heurístico.

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

Figura 3 – Estrutura geral de um método iterativo.

É 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:

• Método da Bissecção: baseia-se no teorema do valor intermediário para “prender”


uma raiz dentre de intervalos cada vez menores;

• Método de Newton-Raphson: utiliza aproximações lineares para melhorar uma


aproximação inicial;
34 Capítulo 2. Zeros de Funções

• Método da Secante: adaptação do método de Newton para contornar a necessidade


de derivadas.

O escolha do método é crucial para determinar o sucesso da aproximação da


solução. Porém, o critério de parada (e a tolerância) utilizado influenciam diretamente na
qualidade da aproximação obtida. Quando pensamos no critério de parada para um método
a pergunta que feita é “A aproximação atual xk para a solução está satisfatoriamente
próxima da raiz exata?”.

Alguns critérios de paradas comuns para os métodos deste capítulo:

• Dada uma tolerância ε, interromper o processo iterativo quando |f (x)| ≤ ε. Este


critério faz sentido pois, se f é uma função contínua, então x está da raiz x quando
f (x) está próximo de zero.

• Erro absoluto: Dada uma tolerância ε, interromper o processo iterativo quando


|xk+1 −xk | ≤ ε, em que xk+1 e xk são duas aproximações consecutivas. Este critério faz
sentido pois, ao nos aproximar da raiz, as aproximações acumulam-se na vizinhança
desta raiz.

|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úmero de iterações: Critério de parada básico para garantir que um processo


iterativo conclua em algum momento. É muito útil em casos nos quais o método não
é convergente para qualquer ponto inicial.

• Critérios particulares de cada método: Alguns métodos podem sugerir critérios de


parada específicos ou que requeiram adaptações dos acima.

Um último fator que influencia diretamente no bom andamento de um método


numérico é a aproximação inicial. Ou seja, o ponto de partida para o método utilizado.
Encontrar uma aproximação inicial boa é um problema tão complexo quanto o próprio
problema de melhorar esta aproximação caso não haja nenhum conhecimento sobre a
função.
2.1. Método da Bissecção 35

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.

2.1 Método da Bissecção


Este método se baseia no teorema do valor intermediário.

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).

Figura 4 – Gráfico de funções satisfazendo as hipóteses do TVI.

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).

O método da bisseção consiste em, partindo de um intervalo inicial que satisfaz o


TVI, particioná-lo em duas partes de modo que sempre um continue contendo a raiz e
satisfazendo as hipóteses do teorema. Dessa forma, encontramos um novo intervalo que
ainda contém uma raiz da função.

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.

Figura 5 – Primeira iteração do método da bisseção.

Dividindo o intervalo [a0 , b0 ] ao meio, obtemos


a0 + b 0
x0 = .
2
Com esta divisão, temos agora, dois subintervalos, [a0 , x0 ] e [x0 , b0 ], como na figura 5.
Fazemos então uma análise nestes dois intervalos para determinar qual deles satisfaz a
hipótese do TVI, isto é, se f (a0 ) · f (x0 ) < 0 ou f (x0 ) · f (b0 ) < 0.

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

Tendo o novo intervalo (com metade do tamanho do anterior), repetimos o processo


de dividir o intervalo ao meio. O método encerra quando algum critério pré-estabelecido
seja atingido. Assim, podemos escrever o método da bisseção como a iteração

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.

• Iteração k = 0: O intervalo é [a0 , b0 ] = [1, 2].


Calculando o ponto médio obtemos x0 = 1.5.
Calculamos a função nos três pontos:

f (x0 ) = −0.75,

f (a0 ) = f (1) = −2,

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:

f (x0 ) · f (b0 ) < 0, f (a0 ) · f (x0 ) > 0.

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

• Iteração k = 1: O intervalo é [a1 , b1 ] = [1.5, 2].


O ponto médio é x1 = 1.75 e o valor da função
nos pontos é:

f (x1 ) = 0.0625,

f (a1 ) = f (1.5) = −0.75,

f (b1 ) = f (2) = 1.

Como |f (x1 )| > 0.01, prosseguimos com as


iterações. Analisando os sinais nos dois inter-
valos:

f (a1 ) · f (x1 ) < 0, f (x1 ) · f (b1 ) > 0.

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.

• Iteração k = 2: Tendo o intervalo [a2 , b2 ] =


[1.5, 1.75], calculamos x2 = 1.625 e

f (x2 ) = −0.359375,

f (a2 ) = f (1.5) = −0.75,

f (b2 ) = f (1.75) = 0.0625.

Como |f (x2 )| = 0.359375 > 0.01, prosseguimos as iterações. Os sinais ficam:

f (a2 ) · f (x2 ) > 0, f (x2 ) · f (b2 ) < 0.

O novo intervalo fica [a3 , b3 ] = [1.625, 1.75].


2.1. Método da Bissecção 39

• Iteração k = 3: Tendo o intervalo [a3 , b3 ] =


[1.625, 1.75], calculamos x3 = 1.6875 e

f (x3 ) = −0.15234375,

f (a3 ) = f (1.625) = −0.359375,

f (b3 ) = f (1.75) = 0.0625.

Como |f (x3 )| = 0.15234375 > 0.01, prosseguimos as iterações. Os sinais ficam:

f (a3 ) · f (x3 ) > 0, f (x3 ) · f (b3 ) < 0.

O novo intervalo é [a4 , b4 ] = [1.6875, 1.75].

• Iteração k = 4: Tendo o intervalo [a4 , b4 ] =


[1.6875, 1.75, calculamos x4 = 1.71875 e

f (x4 ) = −0.045898438,

f (a4 ) = f (1.6875) = −0.15234375,

f (b4 ) = f (1.75) = 0.0625.

Como |f (x4 )| = 0.045898438 > 0.01, prosseguimos as iterações. Os sinais ficam:

f (a4 ) · f (x4 ) > 0, f (x4 ) · f (b4 ) < 0.

O novo intervalo é [a5 , b5 ] = [1.71875, 1.75].

• Iteração k = 5: Tendo o intervalo [a5 , b5 ] =


[1.71875, 1.75], calculamos x5 = 1.734375 e

f (x5 ) = 0.008056641,

f (a5 ) = f (1.71875) = −0.045898438,

f (b5 ) = f (1.75) = 0.0625.

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

Tabela 1 – Resumo das iterações do método da bisseção.

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

De modo geral, um método iterativo consiste em repetir uma sequência de passos


até atingir um determinado critério de parada. Como não temos como saber a priori
quantas iterações serão feitas, a melhor estrutura de repetição neste caso é o while.

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 da tolerância iremos impor também um limitante no número de iterações


como já discutido anteriormente4 . Para isso, utilizaremos também a condição k <= kmax
no while, em que kmax é uma variável de entrada dada.
3
No caso do exemplo apresentado, tivemos TOL = 0.01.
4
Em resumo, esta condição garante que o processo será encerrado em algum momento.
2.1. Método da Bissecção 41

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:

1 function [x , k ] = metBis (f ,a ,b , TOL , kmax )


2
3 k = 0;
4 while abs ( f ( x ) ) > TOL && k <= kmax
5 <Iteração do método>
6 k = k + 1;
7 end

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.

Passamos agora a pensar na implementação do método em si. Para isso, notamos


duas coisas:

• 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.

• Em cada iteração apenas ai ou bi muda de valor em relação a iteração anterior. Como


não iremos guardar as informações das iterações anteriores, utilizaremos as variáveis
a e b de forma escalar e, a cada iteração, sobrescrevemos as informações.

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

Colocando em formato de pseudocódigo, podemos escrever:

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):

Código 2.1 – Método da bisseção.

1 % DESCRICAO : Implementacao do metodo da bissecao .


2 %
3 % ENTRADA :
4 % f - funcao para ser utilizada .
5 % a , b - extremos do intervalo .
6 % TOL - tolerancia desejada .
7 % kmax - numero maximo de iteracoes .
8 % SAIDA :
9 % x - aproximacao final encontrada .
10 % k - numero de iteracoes realizadas .
11 function [x , k ] = metBis (f ,a ,b , TOL , kmax )
12
13 k = 0;
14 x = ( a + b ) /2;
15
16 while abs ( f ( x ) ) > TOL && k <= kmax
17 if f ( a ) * f ( x ) < 0
18 b = x;
19 else
20 a = x;
21 end
2.2. Método de Newton 43

22
23 x = ( a + b ) /2;
24 k = k +1;
25 end

Algumas observações a respeito do método da bisseção:

• A convergência do método é garantida, desde que a função seja contínua num


intervalo [a, b] e que f (a) · f (b) < 0;

• 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;

• As iterações não envolvem cálculos laboriosos.

2.2 Método de Newton


Muito diferente da ideia utilizada no método da bisseção, no método de Newton
utilizamos uma sequência de aproximações lineares para estimar uma raiz da função. Em
outras palavras, neste método substituímos o problema de encontrar a solução de uma
equação não-linear por, iterativamente, fazer aproximações lineares.

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.

Em seguida, calculamos a aproximação x1 como o ponto onde a reta tangente


y = L0 (x) intersecta o eixo x, veja a figura 7. Isto é, x1 é o zero da aproximação linear.

Repetimos o processo partindo do ponto (x1 , f (x1 )), veja a figura 8.

Algebricamente, dado um ponto (x0 , y0 ) e uma declividade m, a equação geral da


reta é:
y − y0 = m(x − x0 ).

No caso de L0 temos o ponto (x0 , f (x0 )) e a declividade da reta tangente5 m = f 0 (x0 ).


5
É claro que aqui precisamos assumir que f é uma função diferenciável.
44 Capítulo 2. Zeros de Funções

Figura 6 – Gráfico de uma função f e da aproximação linear L0 .

Figura 7 – Aproximação x1 obtida a partir da reta y = L0 (x).

Assim, a equação de L0 fica:

y − f (x0 ) = f 0 (x0 )(x − x0 ).

O ponto que procuramos é (x1 , 0) pois está sobre o eixo x. Substituindo na expressão
obtemos:

0 − f (x0 ) = f 0 (x0 )(x1 − x0 )

f (x0 )
⇒x1 = x0 − .
f 0 (x0 )
2.2. Método de Newton 45

Figura 8 – Gráfico de uma função f e da aproximação linear L1 .

Se a aproximação x1 não satisfaz o critério de parada, repetimos o processo


a partir do ponto (x1 , f (x1 )) e obtemos x2 . De modo geral, a aproximação xk+1 do
método de Newton6 é dada por

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 .

Precisaremos da derivada de f : f 0 (x) = 2x + 1.

O processo consiste em simplesmente aplicar iterativamente a expressão do método


de Newton a cada aproximação até que o critério de parada seja atingido.
6
Muitas bibliografias utilizam a denominação Newton-Raphson para este método, deixando o nome
método de Newton para o caso geral de funções de várias variáveis.
46 Capítulo 2. Zeros de Funções

• Iteração k = 0: Primeiro calculamos f e f 0 na aproximação inicial:

f (x0 ) = −2.25, f 0 (x0 ) = 4.

Como x0 não satisfaz o critério de parada vamos calcular a próxima aproximação:


f (x0 )
x1 = x0 − = 2.0625.
f 0 (x0 )
Para esse ponto temos f (x1 ) = 0.31640625 e |f (x1 )| > 10−4 .

• Iteração k = 1:

f (x1 ) = 0.31640625, f 0 (x1 ) = 5.125

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 ) = 0.003811556551161, f 0 (x2 ) = 5.001524390243903

f (x2 )
⇒x3 = x2 − = 2.000000116152868.
f 0 (x2 )
Para esse ponto temos f (x3 ) = 5.807643539412766e − 07 e |f (x3 )| > 10−4 .

Nesta última iteração atingimos o critério de parada desejado e concluímos o


processo. A tabela 2 resume as iterações feitas.

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

Tabela 2 – Resumo das iterações do método de Newton.

Diferente do que ocorre com o método da bisseção onde, se o intervalo inicial


satisfizer a hipótese do TVI, o método irá sempre convergir para uma raiz da função, no
caso do método de Newton temos uma convergência condicional. Isto é, nem sempre o
método irá gerar uma sequência de aproximações {xk } convergente. O teorema a seguir
formaliza o resultado sobre a convergência.
2.2. Método de Newton 47

Teorema 2.2 (Convergência para o método de Newton) Seja f ∈ C 2 [a, b]. Se p ∈


[a, b] é tal que f (p) = 0 e f 0 (p) 6= 0, então, existe um δ > 0, tal que o método de
Newton gera uma sequência {xk } que converge para p para qualquer aproximação inicial
x0 ∈ [p − δ, p + δ].

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.

Na prática, o que é costumeiro é simplesmente executar o método e “torcer” para


que haja convergência ou então combiná-lo com outro método que seja globalmente
convergente (método da bisseção, por exemplo) para ter uma aproximação boa antes de
aplicar o método de Newton.

Algumas observações a respeito do método de Newton:

1. Nem sempre converge (localmente/condicionalmente convergente).

2. Quando converge, a convergência é rápida (quadrática7 );

3. Possui a desvantagem de necessitar de f 0 (x). Para funções de uma variável não


costuma ser um problema grande, mas para funções de várias variáveis em problemas
práticos pode ser problemático.

4. Necessita de duas avaliações de funções em cada iteração (no método da bisseção é


necessário apenas uma).

2.2.1 Implementação

Faremos aqui uma implementação simples do método. Assim como no método da


bisseção, a function irá retornar apenas a última iteração calcula (que satisfaz o critério
de parada) e o número de iterações realizadas.
7
Veja um pouco mais de detalhes na última seção deste capítulo.
48 Capítulo 2. Zeros de Funções

Além da função f , da tolerância TOL e do número máximo de iterações kmax,


incluímos nas variáveis de entrada a derivada de f , que chamaremos de df (lembre-se que
f 0 não é um nome válido para variável), e a aproximação inicial x.

Assim como no método da bisseção, o método de Newton é iterativo e vamos usar


uma estrutura de repetição while para realizar as iterações. O critério de parada será o
mesmo do método da bisseção.

A cada iteração, usamos a informação na variável x, ou seja xk , para calcular a


iteração do método, ou seja xk+1 , e armazenamos o resultado na mesma variável x. Desta
forma, sobrescrevemos a informação e o valor de xk é perdido. O algoritmo 2 esboça o que
é feito no código.

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.

Código 2.2 – Método de Newton.

1 % DESCRICAO : Implementacao do metodo de Newton .


2 %
3 % ENTRADA :
4 % f - funcao para ser utilizada .
5 % df - derivada da funcao f .
6 % x - aproximacao inicial .
7 % TOL - tolerancia desejada .
8 % kmax - numero maximo de iteracoes .
9 % SAIDA :
10 % x - aproximacao final encontrada .
11 % k - numero de iteracoes realizadas .
12 function [x , k ] = metNewton (f , df ,x , TOL , kmax )
13
2.3. Método da Secante 49

14 k = 0;
15 while abs ( f ( x ) ) > TOL && k <= kmax
16 x = x - f ( x ) / df ( x ) ;
17 k = k +1;
18 end

2.3 Método da Secante


Apesar do método de Newton ser rápido, ele exige que calculemos a derivada da
função em cada iteração. Essa informação nem sempre está disponível ou é de fácil obtenção.
Além disso, frequentemente, avaliar a derivada de uma função em um determinado ponto
requer muito mais operações aritméticas do que calcular f (x).

O método da secante é uma alternativa para evitar a necessidade do cálculo da


derivada de f . Da definição de derivada de f no ponto xk temos que

f (x) − f (xk )
f 0 (xk ) = lim .
x→xk x − xk

Em particular, para x = xk−1 próximo de xk , temos

f (xk−1 ) − f (xk )
f 0 (xk ) ≈ .
xk−1 − xk

Substituindo a expressão acima na iteração do método de Newton obtemos o


método da secante é:
f (xk )(xk − xk−1 )
xk+1 = xk − (2.3)
f (xk ) − f (xk−1 )

Observação 2.4 Apesar do método da secante não utilizar a derivada da função f , é


necessário que tenhamos duas aproximações iniciais (xk e xk−1 ) para iniciar o processo.

Geometricamente, o método da secante consiste em usar uma reta secante passando


pelos pontos (xk−1 , f (xk−1 )) (xk , f (xk )), ao invés de uma reta tangente como no método
de Newton, e encontrar onde ela cruza o eixo x.

Exemplo 2.4 Vamos determinar uma aproximação para a raiz de f (x) = x2 + x − 6


considerando x0 = 1 e x1 = 1.5 e o critério de parada |f (xk )| ≤ 10−4 .
50 Capítulo 2. Zeros de Funções

O processo consiste em aplicarmos a expressão do método até encontrarmos a


aproximação desejada.

• Iteração k = 1: Primeiro calculamos f nos dois pontos dados

f (x0 ) = −4, f (x1 ) = −2.25.

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 .

Nesta última iteração atingimos o critério de parada desejado e concluímos o


processo. A tabela 3 resume as iterações feitas.

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

Tabela 3 – Resumo das iterações do método da secante.


2.3. Método da Secante 51

A convergência condicional é herdada do método de Newton e o teorema a respeito


dela é praticamente o mesmo.

Teorema 2.3 (Convergência para o método da secante) Seja f ∈ C 2 [a, b]. Se p ∈


[a, b] é tal que f (p) = 0 e f 0 (p) 6= 0, então, existe um δ > 0, tal que o método da secante
gera uma sequência {xk } que converge para p desde que as aproximações iniciais x0 e x1
pertençam ao intervalo [p − δ, p + δ].

Observações a respeito do método da secante:

• Assim como o método de Newton, o método da secante nem sempre converge;

• Quando converge, a convergência é superlinear. Isso significa que converge mais


rápido que o método da bisseção, mas menos que o de Newton;

• Não necessitamos calcular f 0 (x) como desejávamos (o que é considerado uma vanta-
gem);

• Precisa de duas aproximações iniciais para começar (o que é uma desvantagem


geralmente pequena).

2.3.1 Implementação

A implementação do método da secante segue os mesmos moldes do método


de Newton. O único cuidado a mais necessário é que agora estamos lidando com três
informações (xk−1 , xk e xk+1 ) ao invés de duas. Por causa disso, é preciso usar mais do
que apenas a variável x.

Vamos denotar por x0, x1 e x2 os valores de xk−1 , xk e xk+1 , respectivamente, em


cada iteração. Note que a cada iteração as duas primeiras variáveis precisam ser atualizadas
para que seja possível calcular a nova aproximação.

O diagrama 4 mostra graficamente como as informações devem estar organizadas


e como devemos atualizar as variáveis. Mais especificamente, na iteração k = 2, quando
calculamos x3 , precisamos ter x1 na variável x0 e x2 em x1. Por isso, antes de concluir a
iteração anterior atribuímos:
52 Capítulo 2. Zeros de Funções

x0 x1 x2 x3 x4 ···
k = 1 x0 x1 x2
↓ ↓
k=2 x0 x1 x2
↓ ↓
k=3 x0 x1 x2
.. .. .. ..
. . . .

Tabela 4 – Diagrama da mudança das variáveis no método da secante.

1 x0 = x1 ;
2 x1 = x2 ;

O algoritmo 3 descreve o procedimento para o método da secante.

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

Assim, o código do método da secante fica como abaixo.

Código 2.3 – Método da secante.


1 % DESCRICAO : Implementacao do metodo da secante .
2 %
3 % ENTRADA :
4 % f - funcao para ser utilizada .
5 % x0 , x1 - aproximacoes iniciais .
6 % TOL - tolerancia desejada .
7 % kmax - numero maximo de iteracoes .
8 % SAIDA :
9 % x1 - aproximacao final encontrada .
10 % k - numero de iteracoes realizadas .
11 function [ x1 , k ] = metSec (f , x0 , x1 , TOL , kmax )
12
13 k = 1;
14 while abs ( f ( x1 ) ) > TOL && k <= kmax
15 x2 = x1 - f ( x1 ) *( x1 - x0 ) /( f ( x1 ) -f ( x0 ) ) ;
16 x0 = x1 ;
17 x1 = x2 ;
18 k = k + 1;
19 end

2.4 Comparação dos métodos


Os exemplos mostrados nas seções anteriores não permitem comparar formalmente
a eficiência dos métodos. Além disso, não veremos aqui uma análise forma do desempenho
destes métodos pois isto requer uma grande quantia de ferramentas que fogem da proposta
desta apostila. Veja [2, 3, 4] para uma análise um pouco mais cuidadosa. Aqui apresentamos
apenas algumas informações com intuito de destacar as características dos métodos vistos.

O método da bisseção possui como grande vantagem a convergência global (desde


que o primeiro intervalo satisfaça a hipótese do TVI). Por isso, é ideal para quando não
temos uma boa ideia se a aproximação inicial é boa. Em contrapartida, a desvantagem
54 Capítulo 2. Zeros de Funções

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.

O principal motivo para utilizar o método de Newton é a sua velocidade de


convergência. Quando este método converge o erro decai muito mais rápido que os
outros métodos. De fato, é possível mostrar que ele possui uma convergência chamada de
quadrática, ou de ordem 2, enquanto o da bisseção é linear (ordem 1) e o da secante é
superlinear (ordem 1.618 para o caso sem raízes múltiplas). Outra vantagem deste método
é a possibilidade de utilizá-lo em problemas de várias variáveis. A grande desvantagem do
método de Newton é a convergência local, isto é, precisamos de uma aproximação inicial
boa para que a convergência ocorra. Além disso, necessita de informações sobre a derivada
da função, o que pode ser inacessível ou inviável em problemas práticos.

O método da secante herda a desvantagem da convergência local do método de


Newton. Trocamos a necessidade da derivada pela necessidade de duas aproximações
iniciais, o que costuma ser um bom negócio. Apesar de não convergir tão rápido quanto
o método de Newton, este método converge significantemente bem. De fato, quando a
aproximação está próxima da solução temos xk−1 e xk próximos e a reta secante não difere
muito da reta tangente, portanto, a convergência fica similar ao método de Newton.

O método de Newton e da secante são muito utilizados em problemas envolvendo


sistemas de equações não-lineares. Neste caso, existem diversas formas de aproximar a
derivada (matriz jacobiana) da função então o método da secante se torna um conjunto
de métodos denominados métodos quase-newton. É em dimensões maiores onde o custo
computacional da derivada fica realmente aparente pois, em cada iteração do método de
Newton, é necessário resolver um sistema linear.

Além dos três métodos apresentados neste capítulo, alguns métodos clássicos são:

• Método das cordas;

• Método Regula Falsi ou falsa posição;

• Método pégaso;

• Método de Muller;
2.4. Comparação dos métodos 55

• Método de van Wijngaarden-Dekker-Brent;

• Método do ponto fixo;

• Método de Steffensen.
56 Capítulo 2. Zeros de Funções

2.5 Exercícios

1. Observe a tabela abaixo.

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.

a) A função tem exatamente 4 raízes.

b) A função tem ao menos 3 raízes.

c) A função tem no máximo 3 raízes.

d) Não é possível concluir nada a partir dos dados apresentados.

2. Aplique o método da bisseção, para os seguintes problemas:

a) f (x) = x3 − 9x + 3, com I = [0, 1] e critério de parada |bk − ak | < ε = 10−2 .

b) f (x) = x2 + x − 6, com I = [0, 3] e critério de parada |f (xk )| < ε = 10−2 .

3. Ache, pelo método da bisseção, a raiz da função f (x) = x3 − x2 − 1 com precisão de


quatro casas decimais (isto é, use o critério de parada |xk+1 − xk | < 10−4 ).

4. Aplique o método de Newton para:

a) f (x) = x2 + x − 6 com x0 = 1.5 e critério de parada |xk+1 − xk | < 10−3 .

b) f (x) = x3 − 9x + 3 com x0 = 1.5 e critério de parada |f (xk )| < 10−1 .

c) f (x) = x3 − 9x + 3 com x0 = 0.5 e critério de parada |f (xk )| < 10−4 .



5. Utilize o método de Newton para aproximar o valor de 3 (quem é a função f ?)
com x0 = 1 e critério de parada |xk+1 − xk | < 10−3 .

6. Faça 3 iterações do método da secante para:

a) f (x) = x2 + x − 6 com x0 = 1.5 e x1 = 1.7.

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

a) Bisseção: Use [a, b] = [1, 2].


2+x
b) Ponto fixo: Use g(x) = e x0 = 1.5.
1+x
c) Newton: Use x0 = 1.5.

d) Secante: Use x0 = 1.8 e x1 = 1.5.

8. Explique com suas palavras os pontos fortes e fracos dos métodos estudados.

9. Ache uma aproximação para a raiz da função f (x) = ex − x2 usando o método


que julgar mais adequado com dados iniciais que escolher. Use 3 casas decimais de
precisão.

10. Considere a função f (x) = e−x − cos(x). Aplique os quatro métodos estudados com
2

os seguintes dados iniciais:

a) Bisseção: Use [a, b] = [1, 2].

b) Ponto fixo: Use g(x) = cos(x) − e−x + x e x0 = 1.5.


2

c) Newton: Use x0 = 1.5.

d) Secante: Use x0 = 1 e x1 = 2.

Como critério de parada utilize o erro relativo com T OL = 10−4 . Calcule:

MÉTODO Bisseção Newton Secante


xk (final)
f (xk )
ERRrel
N o de iter.

11. O valor de π pode ser aproximado através da solução das equações:

a) sen(x) = 0;

b) cos(x) + 1 = 0;

Aplique o método de Newton com x0 = 3 e precisão de 10−7 (o critério de parada


será |f (xk )|) em cada caso e compare os resultados obtidos.
x2
12. Seja f (x) = + x(ln(x) − 1). Obtenha (uma aproximação para) os seus pontos
2
críticos através de um método numérico a sua escolha.
58 Capítulo 2. Zeros de Funções

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.

16. O método de Newton estudo é um caso particular do método de Newton para


encontrar zero de funções de várias variáveis. Considere a função F : Rn → Rn .
Supondo que F seja continuamente diferenciável, o método de Newton tem a forma:

xk+1 = xk − JF−1 (xk )F (xk ).

Note que a única mudança foi a troca de 1


f 0 (xk )
pela inversa da matriz jacobiana
JF (xk ). Além disso, note que não é sensato calcular a inversa da matriz jacobiana a
cada iteração. Por isso, o que é feito é, a cada iteração, resolve-se o sistema linear:

JF (xk )δx = F (xk ).

e então fazemos xk+1 = xk − δx.

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

Sistemas de equações lineares aparecem nos mais diversos problemas desde os


geométricos até na aproximação de soluções de equações diferenciais. Ao contrário do
que é visto em um curso de Álgebra Linear clássico, os problemas atualmente lidam com
sistemas lineares de grandes dimensões1 , geralmente.

Métodos diretos como o escalonamento e a fatoração LU são necessários em muitos


problemas, porém em diversos outros é suficiente termos uma aproximação para o vetor
solução do sistema. Neste capítulo apresentamos dois métodos iterativos (assim como os
do capítulo anterior) para aproximar a solução de sistemas lineares.

Em outras palavras, neste capítulo trataremos do problema:

“Dada uma matriz A ∈ Rn × Rn e um vetor b ∈ Rn , encontrar uma


aproximação x ∈ R para o vetor solução do sistema linear Ax = b.”

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.

Como descrito no problema em destaque, a partir de uma aproximação inicial,


encontraremos uma sequência de vetores {xk } que se aproximam da solução do sistema
linear quando k → ∞. Veremos dois métodos (Jacobi e Gauss-Seidel) para realizar esta
tarefa, mas que são casos particulares de um método mais geral chamado de método das
sobrerrelaxações sucessivas (SOR). Não veremos métodos baseados em autovalores como é
caso do método do gradiente conjugado (CG), GMRES, MINRES, BICG e BICGSTAB.

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 Método de Jacobi

Sejam A ∈ Rn × Rn e b ∈ Rn . Considere o sistema linear Ax = b:



+ a12 x2 + · · · + a1n xn = b1




 a11 x1



+ a22 x2 + · · · + a2n xn = b2

a21 x1

 .. (3.1)
.








+ an2 x2 + · · · + ann xn = bn

an1 x1

com os elementos da diagonal aii 6= 0, i = 1, . . . , n. A necessidade dessa hipótese ficará


clara logo a seguir. Além disso, esta condição não limita em nada o que faremos pois
podemos realizar trocas de linhas sempre que necessário.

Matricialmente, o sistema é escrito como:


    
 a11 a12 · · · a1n   x1   b1 
    
 a21 a22 · · · a2n 
  x2 
 b2 
    
 

 . .. . . ..   =  
 .. 
  .
 . .
 .
 . . .   . 
 
.
 
    
an1 an2 · · · ann xn bn

Para construirmos o método de Jacobi, primeiramente olhamos para (3.1) e isolamos


x1 na primeira equação, x2 na segunda equação, . . . , xn na última equação. Com isso, o
sistema é reescrito como:

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

Observação 3.2 Denotaremos usando índices sobrescritos para as iterações e


subscritos para as componentes de um vetor. Ou seja xki representa a componente
i do vetor da iteração k.

O método de Jacobi consiste em, dado a aproximação inicial x0 , obter x1 , x2 , . . . ,


3.1. Método de Jacobi 61

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
 

Solução: O primeiro passo é escrever a expressão da iteração do método de Jacobi


no formato de (3.2):
1

xk+1 = (7 − (2xk2 + xk3 ))


10



 1
1


x2k+1
= (−8 − (xk1 + xk3 ))

 5
1


= (6 − (2xk1 + 3xk2 ))

xk+1


3
10

Agora basta aplicarmos a aproximação inicial e obter a nova iteração (k = 0):

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

forma. Seguindo estes passos obtemos as 6 iterações:


     
 0.7   0.96   0.978 
     
x0 = = =
 1  2
−1.6 ,x −1.86 ,x −1.98 ,
   
  
     
0.6 0.94 0.966
     

     
 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:

• Distância entre xk e xk+1 pela expressão dk = max|xki − xk+1


i |;

• Distância entre xk e xk+1 pela expressão dk = kxk+1 − xk k/kxk k;

• Distância entre Axk e o vetor b pela expressão dk = kb − Axk k.

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.

Exemplo 3.2 Considere a matriz do exemplo anterior:


 
10 2 1
 
1 5 1 .
 
 
2 3 10
 

Vamos verificar se ela é diagonal dominante ou não. Para isso calculamos:

1a linha: |2| + |1| = 3 < |10|,

2a linha: |1| + |1| = 2 < |5|,

3a linha: |2| + |3| = 5 < |10|.

Portanto, a matriz é diagonal dominante e, pelo critério das linhas, independente


da aproximação inicial o método irá convergir para a solução do sistema.

Exemplo 3.3 Considere a matriz:


 
6 2 −1 1
 
1 −7 1 −2


 .
1 5 1 11 
 
 
 
2 3 10 2

Vamos verificar se ela é diagonal dominante ou não:

1a linha: |2| + | − 1| + |1| = 4 < |6|,

2a linha: |1| + |1| + | − 2| = 4 < | − 7|,


64 Capítulo 3. Sistemas Lineares

3a linha: |1| + |5| + |11| = 17 > |1|,

4a linha: |2| + |3| + |10| = 15 > |2|.

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.

A forma como construímos o método de Jacobi é conhecida como forma escalar


(ou não-matricial) pois explicita a iteração do método para cada componente do vetor.
Existe ainda a forma matricial do método que lida com matrizes e vetores.

Sejam L, U e D matrizes tais que A = L + D + U com D sendo a diagonal de A, L


a matriz com todos os elementos abaixo da diagonal de A e os demais nulos e U a matriz
com todos os elementos acima da diagonal de A e os demais nulos, como na figura 9.

Figura 9 – Decomposição da matriz A para a forma matricial do método.

Agora, olhando para o sistema linear Ax = b podemos escrever:

(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

Como D é uma matriz diagonal com todos os elementos não-nulos na diagonal


(supomos inicial que aii 6= 0), ela é inversível. Portanto,

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:

xk+1 = −D−1 (L + U )xk + D−1 b. (3.3)

É 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).

Além disso, como D é inversível e diagonal, sua inversa é conhecida. De fato, a


inversa D−1 é também diagonal e os seus elementos são Dii−1 = 1/aii . Este termo pode ser
visto em (3.2) multiplicando todos os termos.

3.1.1 Implementação

Vamos analisar primeiramente a implementação da forma escalar do método de


Jacobi e depois faremos a implementação da forma matricial.

O primeiro passo para a construção do algoritmo é percebermos que, para a linha i


de (3.2) o método consiste em calcular o somatório:

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

No algoritmo acima, soma armazena o somatório que estamos calculando, x é a


variável que armazena o vetor da iteração k e y é a variável que armazena o vetor da
iteraçã o k + 1. Após calcular o somatório para uma dada linha i calculamos yi subtraindo
soma de bi e dividindo por aii (como está na fórmula (3.2)).

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.

Como variável de entrada incluiremos os dados do problema (matriz A e vetor b), a


aproximação inicial x e as informações para o critério de parada TOL e kmax. As variáveis
3.1. Método de Jacobi 67

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.

de saída serão simplesmente a última aproximação encontrada x (que satisfez o critério de


parada) e o número de iterações realizadas k.

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).

Código 3.1 – Método de Jacobi escalar - primeira forma.

1 % DESCRICAO : Implementa o metodo de Jacobi para um sistema


diagonal dominante .
2 %
3 % ENTRADA :
4 % A - matriz do sistema .
5 % b - lado direito do sistema .
6 % x - aproximacao inicial .
7 % TOL - tolerancia desejada .
8 % kmax - numero maximo de iteracoes .
9 % SAIDA :
10 % x - aproximacao final encontrada .
11 % k - numero de iteracoes realizadas .
68 Capítulo 3. Sistemas Lineares

12 function [x , k ] = metJacobi1 (A ,b ,x , TOL , kmax )


13
14 k = 0;
15 n = length ( b ) ;
16 y = zeros (n ,1) ;
17 while norm (b - A * x ) > TOL && k <= kmax
18 for i = 1: n
19 soma = 0;
20 for j = 1: n
21 if i ~= j
22 soma = soma + A (i , j ) * x ( j ) ;
23 end
24 end
25 y ( i ) = ( b ( i ) - soma ) / A (i , i ) ;
26 end
27 x = y;
28 k = k +1;
29 end

Apesar de funcionar, o código acima é altamente ineficiente e pode ser melhorado


significantemente repensando algumas abordagens. Primeiramente, note que a condição
if i ~= j é testada n2 vezes para cada iteração e só é falsa em n ocasiões (para n = 1000
isso representa 0, 1%).

Podemos revisitar o somatório que deu origem a esse trecho e reescrevê-lo da


seguinte forma:  
n
aij xkj  − aii xki .
X

j=1j6=i

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

Código 3.2 – Método de Jacobi escalar - segunda forma.


1 % DESCRICAO : Implementa o metodo de Jacobi para um sistema
diagonal dominante .
2 %
3 % ENTRADA :
4 % A - matriz do sistema .
5 % b - lado direito do sistema .
6 % x - aproximacao inicial .
7 % TOL - tolerancia desejada .
8 % kmax - numero maximo de iteracoes .
9 % SAIDA :
10 % x - aproximacao final encontrada .
11 % k - numero de iteracoes realizadas .
12 function [x , k ] = metJacobi2 (A ,b ,x , TOL , kmax )
13
14 k = 0;
15 n = length ( b ) ;
16 y = zeros (n ,1) ;
17 while norm (b - A * x ) > TOL && k <= kmax
18 for i = 1: n
19 soma = 0;
20 for j = 1: n
21 soma = soma + A (i , j ) * x ( j ) ;
22 end
23 soma = soma - A (i , i ) * x ( i ) ;
24 y ( i ) = ( b ( i ) - soma ) / A (i , i ) ;
25 end
26 x = y;
27 k = k +1;
28 end

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.

Código 3.3 – Método de Jacobi escalar - terceira forma.

1 % DESCRICAO : Implementa o metodo de Jacobi para um sistema


diagonal dominante .
2 %
3 % ENTRADA :
4 % A - matriz do sistema .
5 % b - lado direito do sistema .
6 % x - aproximacao inicial .
7 % TOL - tolerancia desejada .
8 % kmax - numero maximo de iteracoes .
9 % SAIDA :
10 % x - aproximacao final encontrada .
11 % k - numero de iteracoes realizadas .
12 function [x , k ] = metJacobi3 (A ,b ,x , TOL , kmax )
13
14 k = 0;
15 n = length ( b ) ;
16 y = zeros (n ,1) ;
17 while norm (b - A * x ) > TOL && k <= kmax
18 for i = 1: n
19 soma = A (i ,:) * x - A (i , i ) * x ( i ) ;
20 y ( i ) = ( b ( i ) - soma ) / A (i , i ) ;
21 end
22 x = y;
23 k = k +1;
3.1. Método de Jacobi 71

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.

O passo mais importante da forma matricial consiste em produzir a matriz D−1 (L +


U ) e o vetor D−1 b de forma eficiente/inteligente. Existem diversas formar de fazer isso,
algumas melhores do que a apresentada aqui4 . Começamos por extrair a diagonal da matriz
A e guardando na variável D. Em seguida, subtraímos D de A para obter (L + U ).

1 D = diag ( A ) ; % D eh um vetor .
2 invD = 1./ D ;
3 F = - diag ( invD ) *( A - diag ( D ) ) ;
4 g = diag ( invD ) * b ;

No trecho acima, a function diag extrai a diagonal de A e armazena como vetor em D. Em


seguida, calculamos a diagonal da inversa, que consiste em 1/aii e guardamos na variável
invD. Armazenamos na variável F a matriz −D−1 (L + U ), lembando que a function diag
retorna uma matriz quando recebe um vetor como variável de entrada. Por fim, a variável
g armazena D−1 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.

Código 3.4 – Método de Jacobi matricial.


1 % DESCRICAO : Implementa o metodo de Jacobi para um sistema
diagonal dominante na forma matricial .
2 %
3 % ENTRADA :
4 % A - matriz do sistema .
5 % b - lado direito do sistema .
6 % x - aproximacao inicial .
7 % TOL - tolerancia desejada .
8 % kmax - numero maximo de iteracoes .
4
Veja por exemplo as functions triu e tril.
72 Capítulo 3. Sistemas Lineares

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.

3.2 Método de Gauss-Seidel


Já mencionamos que o método de Jacobi e de Gauss-Seidel são casos particular
do um método chamado SOR. No entanto, a forma mais interessante de ver o método
de Gauss-Seidel é como uma melhoria do método de Jacobi. Veremos que a mudança
entre ele é sutil (tanto analítica quanto computacional), porém esta diferença melhora
significativamente a performance.

Vimos na forma escalar do método de Jacobi (3.2):


1

xk+1 = (b1 − (a12 xk2 + a13 xk3 + · · · + a1n xkn ))


1

a11



1



xk+1 = (b2 − (a21 xk1 + a23 xk3 + · · · + a2n xkn ))



2
a22
 ..
.





1



xk+1 = (bn − (an1 xk1 + an2 xk2 + · · · + an(n−1) xk(n−1) ))



n
ann
3.2. Método de Gauss-Seidel 73

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 ,

assim como xk+1


1 e xk+1
2 quando vamos calcular xk+1
3 , e assim por diante.

Mais do que isso, é natural esperarmos que xk+1


1 esteja mais próximo da primeira
componente da solução exata do sistema do que xk1 , o mesmo vale para as outras componen-
tes. Sendo assim, ao usarmos as componente de xk+1 que estiverem disponível esperamos
reduzir o erro da aproximação em relação ao método de Jacobi.

Assim, o cálculo da aproximação xk+1 pelo método de Gauss-Seidel é dado por

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

Exemplo 3.4 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 Gauss-Seidel fazendo 5 iterações. Use x0 = −1.6 .
 

 
0.6
 

Solução: Assim como no método de Jacobi, primeiro escrevemos a expressão da


iteração do método no formato de (3.4):

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

Agora basta aplicarmos a aproximação inicial e obter a nova iteração (k = 0):


1 1

x11 = (7 − (2x02 + x03 )) = (7 − (2 × (−1.6) + 0.6)) = 0.96


10 10


1 1



x12 = (−8 − (x11 + x03 )) = (−8 − (0.96 + 0.6)) = −1.912
5 5
1 1



= (6 − (2x11 + 3x12 )) = (6 − (2 × 0.96 + 3(−1.912))) = 0.9816

x13


10 10

 
 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

Seguindo estes passos obtemos as 6 iterações:


     
 0.7   0.96   0.98424 
     
x = 0 
 −1.6
 1
,x = 
 −1.912
 2
,x = 
 −1.993168 ,

     
0.6 0.9816 1.0011024
     

     
 0.99852336   0.99995774   1.000007 
     
x = 3
= =
 4  5
−1.9999252 ,x −2.0000461 ,x −2.0000059 .
   
  
     
1.0002729 1.0000223 1.0000004
     

O exemplo acima, em comparação com o mesmo problema usando o método de


Jacobi dá uma ideia de como o método de Gauss-Seidel converge mais rápido (não que isso
prove alguma coisa). É possível mostrar analiticamente que o método de Gauss-Seidel irá
convergir mais rápido que o método de Jacobi mas não vamos mostrar esse teorema aqui.

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

Vamos discutir agora a forma matricial do método de Gauss-Seidel. Assim como


no método de Jacobi, sejam L, D e U matrizes tais que A = L + D + U . Analisando o
sistema Ax = b podemos escrever:

(L + D + U )x = b

⇒ (L + D)x = −U x + b.

A matriz L + D não é diagonal, porém é triangular inferior. Isso torna o sistema


fácil de ser resolvido através de uma substituição progressiva (semelhante a substituição
regressiva usada no escalonamento, porém começando pela primeira linha).

Assim, o método de Gauss-Seidel na forma matricial é:

xk+1 = −(L + D)−1 U xk + (L + D)−1 b. (3.5)

É um pouco mais complicado ver que a expressão (3.5) coincide com (3.4), mas
não impossível.

O mais importante ao implementar o método de Gauss-Seidel na versão matricial


é não calcular explicitamente a inversa de (L + D). Isso é completamente inviável pois a
matriz já permite a substituição progressiva5 .

3.2.1 Implementação

A implementação e análise do método de Gauss-Seidel na forma escalar segue as


mesma ideia do método de Jacobi. De fato, para a primeira forma 3.1 a única mudança é
que agora não utilizamos a variável y. Enquanto no método de Jacobi precisávamos de y
para preservar a iteração anterior, no método de Gauss-Seidel o que queremos é justamente
usar a informação mais atualizada. O código fica como em 3.5:

Código 3.5 – Método de Gauss-Seidel escalar - primeira forma.


1 % DESCRICAO : Implementa o metodo de Gauss - Seidel para um
sistema diagonal dominante .
2 %
3 % ENTRADA :
4 % A - matriz do sistema .
5
Na implementação usaremos a divisão esquerda para resolver este sistema.
76 Capítulo 3. Sistemas Lineares

5 % b - lado direito do sistema .


6 % x - aproximacao inicial .
7 % TOL - tolerancia desejada .
8 % kmax - numero maximo de iteracoes .
9 % SAIDA :
10 % x - aproximacao final encontrada .
11 % k - numero de iteracoes realizadas .
12 function [x , k ] = metGS1 (A ,b ,x , TOL , kmax )
13
14 k = 0;
15 n = length ( b ) ;
16 while norm (b - A * x ) > TOL && k <= kmax
17 for i = 1: n
18 soma = 0;
19 for j = 1: n
20 if i ~= j
21 soma = soma + A (i , j ) * x ( j ) ;
22 end
23 end
24 x ( i ) = ( b ( i ) - soma ) / A (i , i ) ;
25 end
26 k = k +1;
27 end

Para a forma matricial vamos usar a function tril que extrai a matriz L + D de
A, isso simplifica alguns passos.

Código 3.6 – Método de Gauss-Seidel matricial.

1 % DESCRICAO : Implementa o metodo de Gauss - Seidel para um


sistema diagonal
2 % dominante na forma matricial .
3 %
4 % ENTRADA :
3.3. Comparação dos métodos 77

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

3.3 Comparação dos métodos

Os métodos de Jacobi e Gauss-Seidel, apesar de pertencerem a mesma família,


mostram como diferentes implementações e estratégia para um problema pode gerar
soluções melhores ou piores.

Ambas as formas escalares se comparadas a suas versão matriciais são considera-


velmente mais lentos. Isso se deve as caraterísticas do MATLAB de ser uma linguagem
interpretada.

De modo geral, o método de Gauss-Seidel costuma fazer cerca de metade do


número de iterações em relação ao Jacobi para sistemas pequenos (na faixa de 10 × 10). O
interessante é que isso não significa que o método de Gauss-Seidel é melhor que o de Jacobi
pois, dependendo do problema e das aproximações encontradas, mesmo fazendo menos
iterações a versão matricial do Gauss-Seidel leva mais tempo para atingir um mesmo
78 Capítulo 3. Sistemas Lineares

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

2. Para cada matriz da questão anterior, faça 3 iterações do método de Gauss-Seidel


utilizando o mesmo vetor inicial.

3. Mostre que as matrizes da questão anterior são diagonais dominantes, ou seja,


satisfazem o critério das linhas.

4. Explique com as suas palavras a diferença entre o método de Jacobi e o método de


Gauss-Seidel.

5. Aplique o método de Jacobi e o método de Gauss-Seidel para aproximar a solução


do sistema linear 
x+y + z = 10








 x+z =8



−x + 2y + z = 4.


Utilize como critério de parada kxk+1 − xk k < 10−3 .


80 Capítulo 3. Sistemas Lineares

6. Considere a matriz e o vetor:


   
1 2 −2 1
   
A= 1 1 1 , A= 3 .
   
   
2 2 1 5
   

A solução exata do sistema Ax = b é x = [1 1 1]T . Aplique os métodos de Jacobi e


Gauss-Seidel (faça algumas iterações apenas) para tentar resolver o sistema linear
Ax = b. O que estas iterações sugerem a respeito da convergência dos métodos?

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.

8. Considere o processo iterativo para resolver sistemas de equações lineares do tipo


Ax = b definido por:
x(k+1) = (I + A)x(k) − b.

Implemente o método apresentado em uma function e crie um script para determinar


uma aproximação da solução do seguinte sistema linear (escolha a tolerância e a
aproximação inicial que desejar):

−1.1x + 0.1x2 = 1,


1

0.3x − 0.3x2 = 0.


1
81

4 Interpolação

Diversos problemas práticos envolvem funções cuja expressão algébrica é desconhe-


cida, sabendo apenas alguns pontos dela. Muitas vezes isso ocorrer por que estes pontos
são obtidos de experimentos ou medições.

Tendo este conjunto de pontos podemos estar interessados em aproximar o valor


dessa função em outros pontos que não estejam listados sem realizar novas medições ou
experimentos (por motivo de custos, por exemplo). Neste momento entra a noção de
interpolação de funções.

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.

Apesar de podermos escolher essencialmente qualquer conjunto de funções bem


definido, aqui iremos apresentar apenas o conceito de interpolação polinomial. Para o caso
geral você pode procurar sobre os conceitos de base de espaço de funções e ortogonalidade
de funções.

As duas principais aplicações da interpolação são:

• 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.

Em ambos os casos acima, a função g é então usada em substituição à função f .

De modo geral, o primeiro caso ocorre muito em experimentações de laboratório


ou a partir de dados tabelados. Apesar de ser possível utilizar interpolação neste caso,
é mais comum que utilizemos técnicas de regressão que serão vistas no capítulo 5. Já o
segundo caso, é muito utilizada como um meio dentro de outros métodos, como é o caso
da integração numérica no capítulo 6.
82 Capítulo 4. Interpolação

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.

Mais precisamente, vamos lidar com o problema:

“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.”

A figura 10 esboça uma função f um interpolador g e os pontos de interpolação.

Figura 10 – Esboço da interpolação de f por g.

Observação 4.1 Um caminho possível ao interpolar uma função é, dado os n + 1 pontos,


ao invés de produzir um polinômio de grau menor ou igual a n podemos dividi-lo em grupos
menores de pontos consecutivos e obter vários interpoladores, um para cada parte. É claro
que a soma final não será um polinômio pois raramente haverá diferenciabilidade na junção
entre os interpoladores. No entanto, é uma excelente estratégia para evitar problemas
numéricos de imprecisão (como os listados em 1.4) e um fenômeno numérico chamado
fenômeno de Runge.

O objetivo estipulado para este capítulo é preciso e específico. Porém, antes de


tentar estudar qualquer método é importante nos questionarmos se ele é, de fato, alcançável.
83

Será que, dado um conjunto de n + 1 pontos, conseguimos sempre obter um polinômio


interpolador de grau menor ou igual a n? Além disso, se isso for possível, quantos polinômios
existem satisfazendo estas condições?

O teorema a seguir responde as nossas perguntas.

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

Esta expressão forma um sistema linear com (n + 1) equações e (n + 1) incógnitas:



a0 + a1 x0 + a2 x0 2 + . . . + an x0 n = f (x0 )






a0 + a1 x1 + a2 x1 2 + . . . + an x1 n = f (x1 )




..
.







a0 + a1 xn + a2 xn 2 + . . . + an xn n = f (xn )


A matriz desse sistema linear recebe o nome de matriz de Vandermonde:


 
1
2 n
x0 x 0 . . . x0 
 
1 x1 x 1 2 . . . x 1 n 
 
A=
 
. .. .. . . .. 
.
. . . . . 

 
1 xn xn 2 . . . xn n
 
84 Capítulo 4. Interpolação

É possível mostrar que, se x0 , x1 , x2 , . . . , xn são todos distintos como é o nosso caso,


então a matriz é inversível (det(A) 6= 0). Portanto, o sistema admite uma única solução.

Em outras palavras, existe exatamente um único conjunto de coeficientes a0 , a1 ,


a2 , . . . , an para os quais pn (x) coincidirá com f (x) no pontos xi , i = 1, . . . , n. E era isso
que queríamos mostrar.

A demonstração do teorema acima é particularmente interessante para nós pois,


além de mostrar a veracidade do resultado, nos fornece uma forma de calcular o polinômio
interpolador. Para isso, basta construir o sistema linear com os pontos dados e resolvê-lo
(por escalonamento, por exemplo).

Exemplo 4.1 Problema: Determine o polinômio interpolador dos pontos da tabela:

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 )


ou ainda, substituindo os valores:



a0 −a1 +a2 =4






 a0 =1


a0 +2a1 +4a2 = −1


Temos imediatamente que a0 = 1 e, com um pouco de manipulação algébrica,


encontramos a1 = −7/3 e a2 = 2/3. Portanto, o polinômio interpolador para os pontos
7 2
dados é p2 (x) = 1 − x + x2 .
3 3
4.1. Forma de Lagrange 85

Podemos facilmente verificar que o polinômio encontrado de fato é o interpolador.


Para isso, basta avaliá-lo nos pontos dados:

p2 (x0 ) = p2 (−1) = 4 = f (x0 ),

p2 (x1 ) = p2 (0) = 1 = f (x1 ),

p2 (x2 ) = p2 (2) = −1 = f (x2 ).

O método apresentado no exemplo acima, apesar de funcional, não é adequado


para encontrar o interpolador. Primeiramente, pelas questões numéricas apresentadas em
1.4, se n for um pouco maior o solução numérica do sistema pode ficar consideravelmente
diferente da analítica. Ou seja, para n > 10, por exemplo, os efeitos numéricos na solução
do sistema podem ser tais que o polinômio encontrado não interpola os pontos.

Se isso não bastasse, o esforço computacional necessário para resolver o sistema


linear é muito superior do que os métodos que iremos apresentar aqui. Falaremos mais
sobre isso na última seção desse capítulo.

Estudaremos 3 métodos/formas para obtenção do polinômio interpolador. Como este


interpolador é único, as 3 formas devem, obrigatoriamente, resultar no mesmo polinômio
(a menos de arredondamentos). Apesar de fornecerem a mesma resposta, estes métodos
tem propriedade particulares que fazem com que um seja mais adequado em determinados
momentos, e em outros uma outra forma.

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.

4.1 Forma de Lagrange

Na abordagem apresentada na introdução deste capítulo, usando a matriz de


Vandermonde, usamos o que é conhecido como base canônica para os polinômios (1,
x, x2 , . . . , xn ) para obter os coeficientes da combinação linear que produz o polinômio
interpolador. Assim como ocorre com os espaços vetoriais, a base canônica não é a única
possível. Por exemplo, os polinômios x + 1, x2 + x e x2 + 1 formam uma base para os
86 Capítulo 4. Interpolação

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.

A estratégia da forma de Lagrange consiste em fixar os coeficientes e construir


uma base de polinômios para o problema em questão de forma que quando fazermos a
combinação destes coeficientes com esta base obtemos o polinômio interpolador.

Sejam f (x) uma função definida em x0 , x1 , x2 , . . . , xn , (n + 1) pontos distintos,


e yi = f (xi ), i = 0, . . . , n. Considere pn (x) o polinômio de grau menor ou igual a n que
interpola f nos pontos dados. Podemos escrever pn (x) como combinação dos polinômios
Lk na forma de Lagrange:
n
pn (x) = y0 L0 (x) + y1 L1 (x) + . . . + yn Ln (x) = yk Lk (x), (4.1)
X

k=0

em que Lk (x) são chamados de polinômios de Lagrange.

Vamos mostrar que os polinômios Lk satisfazem um conjunto de propriedades que


irão implicar que a combinação acima gera o polinômio interpolador. Diferente da maioria
das bibliografias, vamos tentar intuir a forma destes polinômios antes de apresentá-los.

Os polinômios de Lagrange devem satisfazer as seguintes propriedades:

P1) Ter grau exatamente1 n;

P2) Para um k fixo, Lk (xk ) = 1;

P3) Para um k fixo e i 6= k, Lk (xi ) = 0;

Um conjunto de polinômios Lk que satisfaça estas três propriedades irremediavel-


mente produzirá um polinômio interpolador na forma (4.1) para os pontos dados. De fato,
se combinarmos quaisquer polinômios de grau n obteremos um polinômio de grau menor
ou igual a n (pode ser que o coeficiente de xn se cancele o o polinômio resultante diminua
de grau).

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:

pn (xi ) = y0 L0 (xi ) + y1 L1 (xi ) + . . . + yi Li (xi ) + . . . + yn Ln (xi ) = yi .


1
Diferente do interpolador que tem grau menor ou igual a n, os polinômios de Lagrange devem ter grau
n sempre.
4.1. Forma de Lagrange 87

Ou seja, se encontrarmos um conjunto qualquer de polinômios que satisfaçam as


três propriedades poderemos obter o polinômio interpolador usando a forma de Lagrange
(4.1).

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.

Para clarificar, se n = 3 temos

• 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 :

Lk (x) = a(x − x0 )(x − x1 ) · · · (x − xk−1 )(x − xk+1 ) · · · (x − xn ), k = 0, . . . , n,

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 = Lk (xk ) = a(xk − x0 )(xk − x1 ) · · · (xk − xk−1 )(xk − xk+1 ) · · · (xk − xn )

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

Assim, os polinômios de Lagrange são:

(x − x0 )(x − x1 ) · · · (x − xk−1 )(x − xk+1 ) · · · (x − xn )


Lk (x) = , (4.2)
(xk − x0 )(xk − x1 ) · · · (xk − xk−1 )(xk − xk+1 ) · · · (xk − xn )

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

Determine o polinômio interpolador usando a fórmula de Lagrange e estime f (0, 8).

Solução: Primeiramente calculamos os polinômios de Lagrange. Como temos 3


pontos, teremos 3 polinômios de grau 2:

(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)

Tome um momento para verificar que as propriedades P 2 e P 3 são válidas, isto é,

L0 (x0 ) = 1, L0 (x1 ) = 0, L0 (x2 ) = 0,

L1 (x0 ) = 0, L1 (x1 ) = 1, L1 (x2 ) = 0,

L2 (x0 ) = 0, L2 (x1 ) = 0, L2 (x2 ) = 1,


4.1. Forma de Lagrange 89

Substituindo os polinômios de Lagrange na forma (4.1) obtemos:

p2 (x) = y0 L0 (x) + y1 L1 (x) + y2 L2 (x) =

= 1, 3(2x2 − 3x + 1) + 2, 5(−4x2 + 4x) + 0, 9(2x2 − x) =

= −5, 6x2 + 5, 2x + 1, 3.

Você pode fazer a verificação de que o polinômio encontrado é de fato o interpolador


avaliando-o nos pontos.

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

Para implementar a forma de Lagrange (e as outras formas também) vamos usar


os polinômios como descrito em 8.5.1, isto é, usando o Symbolic Math Toolbox.

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.

O que precisamos entender na hora de implementar esta forma é que temos um


produtório dentro de um somatório. Existem formas mais eficientes, porém aqui faremos
algo semelhante ao que foi feito no exemplo 8.30.

IMPORTANTE: Temos que cuidar nesta implementação que n é o grau do polinômio


interpolador, porém temos n + 1 pontos. Vamos denotar por m a variável com o número de
pontos dados. Portanto, m = length(X), em que X é o vetor com as abscissas dos pontos
de interpolação.

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

em que L é o polinômio Lk (x).

Agora, para calcular L para cada k vamos fazer o produtório do numerador e do


denominador de (4.2). Temos que lembrar que j também irá de 1 até m e que devemos
excluir o caso j==k. Assim, o algoritmo pode ser escrito como:
L = 1;
para j = 1 até m
se j 6= k
L = L · (x − Xj )/(Xk − Xj );
fim
fim

Assim, misturando um pouco da sintaxe do MATLAB, temos o algoritmo da forma


de Lagrange para o interpolador:

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

Código 4.1 – Forma de Lagrange para interpolação.


1 % DESCRICAO : Implementacao da forma de Lagrange para
interpolacao .
2 %
3 % ENTRADA :
4 % x , y - coordenadas dos pontos .
5 % SAIDA :
6 % p - polinomio interpolador .
7 function p = formaLagrange (X , Y )
8
9 syms x % Declara a variavel simbolica .
10
11 % m = numero de pontos .
12 % m = n +1;
13 m = length ( X ) ;
14
15 p = 0;
16 for k = 1: m
17 L = 1;
18 for j = 1: m
19 if j ~= k
20 L = L *( x - X ( j ) ) /( X ( k ) - X ( j ) ) ;
21 end
22 end
23 p = p + Y(k)*L;
24 end

4.2 Forma de Newton


Para falarmos da forma de Newton precisamos primeiramente definir o conceito de
diferença dividida.

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

nos pontos xi , i = 0, 1, . . ., n por:

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 , . . . , xn ] − f [x0 , x1 , x2 , . . . , xn−1 ]


f [x0 , x1 , x2 , . . . , xn ] = . (4.3)
(xn − x0 )

Em palavras, as diferenças divididas são definidas recursivamente a partir das


ordens anteriores. As de ordem 0 são simplesmente o valor da função f no ponto dado. Já
as de ordem 1 são definidas a partir das de ordem 0 usando (4.3):

f [x1 ] − f [x0 ] f (x1 ) − f (x0 )


f [x0 , x1 ] = =
(x1 − x0 ) x1 − x0

f [x2 ] − f [x1 ] f (x2 ) − f (x1 )


f [x1 , x2 ] = =
(x2 − x1 ) x2 − x1

..
.

f [xn ] − f [xn−1 ] f (xn ) − f (xn−1 )


f [xn−1 , xn ] = = .
(xn − xn−1 ) xn − xn−1

Agora, as diferenças divididas de ordem 2 são calculadas usando as de ordem 1:

f [x1 , x2 ] − f [x0 , x1 ]
f [x0 , x1 , x2 ] =
(x2 − x0 )

f [x2 , x3 ] − f [x1 , x2 ]
f [x1 , x2 , x3 ] =
(x3 − x1 )

..
.

f [xn−1 , xn ] − f [xn−2 , xn−1 ]


f [xn−2 , xn−1 , xn ] =
(xn − xn−2 )

Note que teremos n diferenças divididas de ordem 0, n − 1 de ordem 1 e indo até 1


de ordem n. Podemos tabelar de forma conveniente as diferenças divididas para ajudar a
organizar as contas, veja a tabela 5.
4.2. Forma de Newton 93

x Ordem 0 Ordem 1 Ordem 2 Ordem 3


x0 f [x0 ] f [x0 , x1 ] f [x0 , x1 , x2 ] f [x0 , x1 , x2 , x3 ]
x1 f [x1 ] f [x1 , x2 ] f [x1 , x2 , x3 ]
x2 f [x2 ] f [x2 , x3 ]
x3 f [x3 ]

Tabela 5 – Organização da tabela de diferenças divididas.

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

Construa sua tabela de diferenças divididas.

Solução: Começamos pela diferença dividida de ordem 0 e vamos deslocando para


a direita calculando as de ordem maior. Note que, como neste exemplo temos 5 pontos,
n = 4 e, portanto, temos as diferenças divididas até a ordem 4.

• Ordem 0: lembre-se que a diferença dividida de ordem 0 é o próprio valor da função


nos pontos, portanto precisamos apenas inserir os valores de xi e f (xi ) que são
dados:

x Ordem 0 Ordem 1 Ordem 2 Ordem 3 Ordem 4


−1 1 f [x0 , x1 ] f [x0 , x1 , x2 ] f [x0 , x1 , x2 , x3 ] f [x0 , x1 , x2 , x3 , x4 ]
0 1 f [x1 , x2 ] f [x1 , x2 , x3 ] f [x1 , x2 , x3 , x4 ]
1 0 f [x2 , x3 ] f [x2 , x3 , x4 ]
2 −1 f [x3 , x4 ]
3 −2

• Ordem 1: Temos 4 diferenças divididas de ordem 1:


f [x1 ] − f [x0 ] 1−1
f [x0 , x1 ] = = =0
(x1 − x0 ) 0 − (−1)

f [x2 ] − f [x1 ] 0−1


f [x1 , x2 ] = = = −1
(x2 − x1 ) 1−0

f [x3 ] − f [x2 ] −1 − 0
f [x2 , x3 ] = = = −1
(x3 − x2 ) 2−1

f [x4 ] − f [x3 ] −2 − (−1)


f [x3 , x4 ] = = = −1
(x4 − x3 ) 3−2
94 Capítulo 4. Interpolação

Atualizamos a tabela:

x Ordem 0 Ordem 1 Ordem 2 Ordem 3 Ordem 4


−1 1 0 f [x0 , x1 , x2 ] f [x0 , x1 , x2 , x3 ] f [x0 , x1 , x2 , x3 , x4 ]
0 1 −1 f [x1 , x2 , x3 ] f [x1 , x2 , x3 , x4 ]
1 0 −1 f [x2 , x3 , x4 ]
2 −1 −1
3 −2

• Ordem 2: Temos 3 diferenças divididas:

f [x1 , x2 ] − f [x0 , x1 ] −1 − 0 1
f [x0 , x1 , x2 ] = = =−
(x2 − x0 ) 1 − (−1) 2

f [x2 , x3 ] − f [x1 , x2 ] −1 − (−1)


f [x1 , x2 , x3 ] = = =0
(x3 − x1 ) 2−0

f [x3 , x4 ] − f [x2 , x3 ] −1 − (−1)


f [x2 , x3 , x4 ] = = =0
(x4 − x2 ) 3−1

Atualizamos a tabela:

x Ordem 0 Ordem 1 Ordem 2 Ordem 3 Ordem 4


−1 1 0 −1/2 f [x0 , x1 , x2 , x3 ] f [x0 , x1 , x2 , x3 , x4 ]
0 1 −1 0 f [x1 , x2 , x3 , x4 ]
1 0 −1 0
2 −1 −1
3 −2

• Ordem 3: Temos 2 diferenças divididas:

f [x1 , x2 , x3 ] − f [x0 , x1 , x2 ] 0 − (−1/2) 1


f [x0 , x1 , x2 , x3 ] = = =
(x3 − x0 ) 2 − (−1) 6

f [x2 , x3 , x4 ] − f [x1 , x2 , x3 ] 0−0


f [x1 , x2 , x3 , x4 ] = = =0
(x4 − x1 ) 3−0

Atualizamos a tabela:
4.2. Forma de Newton 95

x Ordem 0 Ordem 1 Ordem 2 Ordem 3 Ordem 4


−1 1 0 −1/2 1/6 f [x0 , x1 , x2 , x3 , x4 ]
0 1 −1 0 0
1 0 −1 0
2 −1 −1
3 −2

• Ordem 4: Temos 1 apenas uma diferença dividida:

f [x1 , x2 , x3 , x4 ] − f [x0 , x1 , x2 , x3 ] 0 − 1/6 1


f [x0 , x1 , x2 , x3 , x4 ] = = =−
(x4 − x0 ) 3 − (−1) 24

Atualizamos a tabela e encerramos a conta:

x Ordem 0 Ordem 1 Ordem 2 Ordem 3 Ordem 4


−1 1 0 −1/2 1/6 −1/24
0 1 −1 0 0
1 0 −1 0
2 −1 −1
3 −2

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:

f [x0 , x1 , x2 ] = f [x0 , x2 , x1 ] = f [x1 , x0 , x2 ] = f [x1 , x2 , x0 ] = f [x2 , x1 , x0 ] = f [x2 , x0 , x1 ].

Esta propriedade de permutação permitirá definir a forma de Newton.


96 Capítulo 4. Interpolação

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 )

⇒f (x) = f (x0 ) + (x − x0 )f [x, x0 ] .


| {z } | {z }
p0 (x) E0 (x)

Na expressão acima temos f (x) escrito como a soma do polinômio interpolador de


ordem 0 com a função E0 (x), que é o erro da aproximação da função f pelo polinômio
interpolador p0 .

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 (x) − f (x0 ) − (x − x0 )f [x0 , x1 ]


=
(x − x0 )(x − x1 )

⇒f (x) = f (x0 ) + (x − x0 )f [x0 , x1 ] + (x − x0 )(x − x1 )f [x0 , x1 , x]


| {z } | {z }
p1 (x) E1 (x)

Podemos verificar que a expressão p1 (x) indicada acima é, de fato, o polinômio


interpolador (isto é, p1 (xi ) = f (xi )):

p1 (x0 ) = f (x0 ) + (x0 − x0 )f [x0 , x1 ] = f (x0 );

f (x1 ) − f (x0 )
p1 (x1 ) = f (x0 ) + (x1 − x0 )f [x0 , x1 ] = f (x0 ) + (x1 − x0 ) =
x1 − x0

= f (x0 ) + f (x1 ) − f (x0 ) = f (x1 ).


4.2. Forma de Newton 97

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 é:

pn (x) = f [x0 ] + (x − x0 )f [x0 , x1 ] + (x − x0 )(x − x1 )f [x0 , x1 , x2 ]+

+ . . . + (x − x0 )(x − x1 ) . . . (x − xn−1 )f [x0 , x1 , . . . , xn ] (4.4)

O erro é dado por

En (x) = (x − x0 )(x − x1 ) . . . (x − xn )f [x0 , x1 , . . . , xn , x].

É importante notar que a expressão da forma de Newton (4.4) usa os elementos


da tabela de diferenças divididas para a construção do polinômio interpolador. Mais
especificamente, todos os elementos da primeira linha da tabela.

Além disso, note que o termo (x − xn ) não aparece na expressão do polinômio


interpolador (4.4). De fato, se tivéssemos usado todos os n+1 termos (x−xi ) multiplicados,
teríamos possivelmente um polinômio de grau maior que n.

Exemplo 4.4 Problema: Usando a forma de Newton, determine o polinômio de grau


interpolador dos pontos da tabela:

x −1 0 2
f (x) 4 1 −1

Solução: O primeiro passo é calcular a tabela de diferenças divididas:

x Ordem 0 Ordem 1 Ordem 2


−1 4 −3 2/3
0 1 −1
2 −1
98 Capítulo 4. Interpolação

Os valores que precisaremos são: f [x0 ] = 4, f [x0 , x1 ] = −3 e f [x0 , x1 , x2 ] = 2/3.


Substituindo em (4.4) obtemos:

p2 (x) = f [x0 ] + (x − x0 )f [x0 , x1 ] + (x − x0 )(x − x1 )f [x0 , x1 , x2 ] =

= 4 + (x + 1)(−3) + (x + 1)(x − 0)(2/3) =

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

A implementação da forma de Newton é separada em duas partes. A primeira cria


a tabela de diferenças divididas e a segunda calcula o polinômio.

A parte mais complicada deste código é entender como os índices se comportam na


construção da matriz de diferenças divididas. Olhar para o exemplo 4.3 ajuda a entendê-los.
Usar uma folha para anotar os índices e perceber os padrões ajuda a entender a construção.

Se m é o número de pontos dados (isto é, m = n + 1) então o que vamos fazer é


construir uma matriz m × m contendo a tabela de diferenças divididas, sem a coluna da
esquerda que contém o vetor X.

A primeira coluna da matriz temos gratuitamente pois é exatamente igual ao vetor


de entrada Y. A atribuição pode ser feita através do comando T(:,1) = Y;, em que T é a
variável que irá conter a tabela.

Como a primeira coluna já está preenchida e a tabela tem m colunas, fazemos um


loop indo de 2 até m para percorrer cada uma das colunas.

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}.
???

Na expressão acima os índices, apesar de subscritos, correspondem as índices das variáveis.

Para o denominador usamos duas componentes do vetor X. A segunda corresponde


sempre o índice da linha, isto é, i. Já a primeira componente utilizada varia com a linha e
a coluna. De fato, a tabela abaixo indica os índices que utilizamos3 :

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

Na expressão acima os índices, apesar de subscritos, correspondem as índices das variáveis.


3
Os índices da tabela correspondem as variáveis que aparecerão no código e, portanto, são acrescidos de
1 unidade em relação aos índices do exemplo.
100 Capítulo 4. Interpolação

O algoritmo da construção da matriz fica:

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

DICA: Poderíamos implementar a construção dessa matriz de diferenças divididas em uma


function individual e chamá-la dentro da function que calcula o polinômio interpolador,
porém não faremos isso aqui. Deixaremos para apresentar o código deste trecho na versão
final da implementação.

Tendo a matriz T com a tabela de diferenças divididas completa nos voltamos a


implementar a expressão (4.4).

Primeiramente, percebemos cada polinômio de cada termo que aparece na expressão


(4.4) está contido no seguinte, isto é:

1o termo: 1

2o termo: (x − x0 )

3o termo: (x − x0 )(x − x1 )

4o termo: (x − x0 )(x − x1 )(x − x2 )

5o termo: (x − x0 )(x − x1 )(x − x2 )(x − x3 )

.. ..
. .

(n + 1)o termo: (x − x0 )(x − x1 ) . . . (x − xn−1 )

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

O algoritmo fica na seguinte forma:


polin = 1;
para j = 2 até m
polin = polin · (x − Xj−1 );
fim

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

em que p é a variável que armazena o polinômio interpolador.

Isso encerra a segunda parte do algoritmo. O código a seguir implementa todo o


algoritmo discutido nesta seção.

Código 4.2 – Forma de Newton para interpolação.


1 % DESCRICAO : Implementacao da forma de Newton para
interpolacao .
2 %
3 % ENTRADA :
4 % x , y - coordenadas dos pontos .
5 % SAIDA :
6 % p - polinomio interpolador .
7 function p = formaNewton (X , Y )
8
9 syms x
10
11 % m = numero de pontos .
12 % m = n +1;
102 Capítulo 4. Interpolação

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

4.3 Forma de Newton-Gregory

A forma de Newton-Gregory é um caso particular da forma de Newton para quando


as abscissas dos pontos de interpolação são igualmente espaçados.

Similar a forma de Newton, definimos o conceito de diferença finita e mostramos


como escrever o polinômio interpolador usando-as. Seja f (x) uma função contínua no
intervalo [a, b]. Sejam x0 , x1 , . . . , xn (n + 1) pontos distintos do intervalo [a, b] tais que
xi+1 − xi = h, para i = 0, 1, . . . , (n − 1).

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 )

A diferença finita de ordem n de uma função f (x) no ponto xi é dada por:

∆n f (xi ) = ∆n−1 f (xi+1 ) − ∆n−1 f (xi ). (4.5)


4.3. Forma de Newton-Gregory 103

Note que a notação da diferença finita é diferente da dividida, mas a expressão é


semelhante (com exceção do denominador). De fato, também podemos organizar o cálculo
das diferenças finitas conforme a tabela:

x ∆0 f (x) ∆1 f (x) ∆2 f (x) ∆3 f (x)


x0 ∆0 f (x0 ) ∆1 f (x0 ) ∆2 f (x0 ) ∆3 f (x0 )
x1 ∆0 f (x1 ) ∆1 f (x1 ) ∆2 f (x1 )
x2 ∆0 f (x2 ) ∆1 f (x2 )
x3 ∆0 f (x3 )

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

Construa sua tabela de diferenças finitas.

Solução: Primeiramente, precisamos verificar que os pontos são igualmente espa-


çados. Como a distância entre os pontos consecutivos é sempre h = 0, 2 podemos calcular
a tabela.

Assim como na tabela de diferenças divididas, começamos por anotar os valores de


xi (que neste caso não são utilizados na conta) e os termos de primeira ordem (que são os
próprios valores de f (xi )):

x ∆0 f (x) ∆1 f (x) ∆2 f (x) ∆3 f (x)


0, 5 5, 8 ∆1 f (x0 ) ∆2 f (x0 ) ∆3 f (x0 )
0, 7 7, 9 ∆1 f (x1 ) ∆2 f (x1 )
0, 9 10, 1 ∆1 f (x2 )
1, 1 12, 3

• Ordem 1: Temos 3 diferenças finitas:

x ∆0 f (x) ∆1 f (x) ∆2 f (x) ∆3 f (x)


∆1 f (x0 ) = ∆0 f (x1 ) − ∆0 f (x0 ) = 2, 1 0, 5 5, 8 2, 1 ∆2 f (x0 ) ∆3 f (x0 )
0, 7 7, 9 2, 2 ∆2 f (x1 )
∆1 f (x1 ) = ∆0 f (x2 ) − ∆0 f (x1 ) = 2, 2
0, 9 10, 1 2, 2
∆1 f (x2 ) = ∆0 f (x3 ) − ∆0 f (x2 ) = 2, 2 1, 1 12, 3
104 Capítulo 4. Interpolação

• Ordem 2: Temos 2 diferenças finitas:

x ∆0 f (x) ∆1 f (x) ∆2 f (x) ∆3 f (x)


0, 5 5, 8 2, 1 0, 1 ∆3 f (x0 )
∆ f (x0 ) = ∆ f (x1 ) − ∆ f (x0 ) = 0, 1
2 1 1
0, 7 7, 9 2, 2 0

∆2 f (x1 ) = ∆1 f (x2 ) − ∆1 f (x1 ) = 0 0, 9 10, 1 2, 2


1, 1 12, 3

• Ordem 3: Temos apenas 1 diferenças finitas:

x ∆0 f (x) ∆1 f (x) ∆2 f (x) ∆3 f (x)


0, 5 5, 8 2, 1 0, 1 −0, 1
0, 7 7, 9 2, 2 0
∆3 f (x0 ) = ∆2 f (x1 ) − ∆2 f (x0 ) = −0, 1
0, 9 10, 1 2, 2
1, 1 12, 3

O teorema a seguir estabelece a relação entre as diferenças divididas e finitas e


permite que escrevamos a forma de Newton-Gregory.

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!


Substituindo a equação do teorema acima na forma de Newton para pn (x) temos a


forma de Newton-Gregory para o interpolador:

∆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

Determine o polinômio interpolador pela forma de Newton-Gregory e use-o para aproximar


o valor de f (1, 3).

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.

O segundo passo é construir a tabela de diferenças finitas:

x ∆0 f (x) ∆1 f (x) ∆2 f (x)


0 1 −1/2 2/3
0, 1 1/2 1/6
0, 2 2/3

O terceiro e último passo é substituir os dados da primeira linha da tabela e os


valores de xi na forma (4.6):

∆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

Para aproximar f em x = 1, 3 basta usarmos o polinômio interpolador: f (1, 3) ≈


p2 (1, 3) = 93/2 = 46, 5.

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

A implementação da forma de Newton-Gregory é muito similar a da forma de


Newton.

Primeiramente, para construir a tabela de diferenças finitas usamos o mesmo


106 Capítulo 4. Interpolação

algoritmo removendo apenas o denominador da expressã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

A implementação da forma de Newton-Gregory é dada abaixo.

Código 4.3 – Forma de Newton-Gregory para interpolação.


1 % DESCRICAO : Implementacao da forma de Newton para
interpolacao .
2 %
3 % ENTRADA :
4 % x , y - coordenadas dos pontos .
5 % SAIDA :
6 % p - polinomio interpolador .
7 function p = formaNewtonGregory (X , Y )
8
9 syms x
10
11 % m = numero de pontos .
12 % m = n +1;
13 m = length ( X ) ;
14 T = zeros ( m ) ;
15 T (: ,1) = Y ;
16 for j = 2: m
4.4. Comparação dos métodos 107

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.

4.4 Comparação dos métodos


Como as três formas não são processos iterativos não faz sentido compará-los deste
modo. No entanto, é possível contar o número de operações aritméticas necessárias (no
pior dos casos) para obter a resposta. A tabela abaixo apresenta estas quantias para um
conjunto de n pontos.

Adições Multiplicações Divisões Total

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.

Apesar de fazer uma quantia significantemente maior de operações a forma de


Lagrange possui uma vantagem em relação aos demais. Quando é necessário interpolar
diversos conjuntos de dados paralelamente em que as abscissas são as mesmas, mudando
apenas as ordenadas, a forma de Lagrange tira proveito do fato que não precisaremos
recalcular os polinômios Lk . Sendo assim, economiza grande parte das operações.

A forma de Newton-Gregory tem o limitante de que os pontos precisam ser igual-


mente espaçados. Apesar de, na maioria dos casos, os pontos serem igualmente espaçados
isso pode impedir a utilização desta forma.

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

1. Escreva com detalhes e nas suas palavras a demonstração do teorema 4.1.

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).

3. a) Utilizando x0 = 2, x1 = 2.75 e x2 = 4, encontre o polinômio de Lagrange de grau


1 35 49
2 que interpola a função f (x) = 1/x nesses pontos. Resposta: x2 − x+ .
22 88 44
b) Utilize o polinômio construído no item a) para aproximar o valor de f (3).
Resposta: 0.32955.

c) Qual foi o erro cometido na aproximação do item anterior?

4. Considere os dados da tabela abaixo:

xi 0 1 2 3
f (xi ) 0.0 0.8415 0.9093 0.1411

a) Construa o polinômio interpolador de Lagrange que interpola os pontos da


tabela.

b) Construa o polinômio interpolador de Newton que interpola os pontos da tabela.

c) Construa o polinômio interpolador de Newton-Gregory que interpola os pontos


da tabela.

Resposta: −0, 01038x3 − 0.35x2 + 1.2x.

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.

6. Considere os dados da tabela abaixo:

xi -0.6 -0.5 0 0.2 0.4 0.7


f (xi ) -0.15 -0.1 0 0.4 1 1.9

a) Construa o polinômio interpolador de Lagrange que interpola os pontos da


tabela.

b) Construa o polinômio interpolador de Newton que interpola os pontos da tabela.


110 Capítulo 4. Interpolação

c) Construa o polinômio interpolador de Newton-Gregory que interpola os pontos


da tabela.

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 .

8. A tabela a seguir relaciona o calor específico da água com a temperatura.

t, o C cp , kcal/(kg o C)
200 1.075
220 1.102
240 1.136
260 1.183
280 1.250

Calcule a capacidade calorífica cp da água a t = 250o C usando o método de interpo-


lação de sua preferência.

9. Sabendo que cos(0) = 1, cos(π/6) = 3/2, cos(π/3) = 1/2 e cos(π/2) = 0, calcule
uma aproximação para cos(π/4). Utilize o método que preferir. Calcule o erro relativo
entre a aproximação encontrada e valor dado pelo MATLAB.

10. Os pontos da tabela a seguir correspondem a duas funções f1 e f2 . Calcule o polinômio


interpolador para ambas usando a forma de Lagrange e de Newton-Gregory. Qual
das duas formas requer mais esforço neste caso (várias interpolações com os mesmos
valores de x)?

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.

12. Adicione à implementação do método de Newton-Gregory um teste para verificar se


os pontos são igualmente espaçados.
4.5. Exercícios 111

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:

1 xx = linspace ( min ( x ) , max ( x ) ,100) ;


2 yy = subs (p , xx ) ;
3 plot (x ,y , 'r * ' ,xx , yy , 'b ')

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:

• Declare n = 10;, x = (1:n)'; e y = rand(n,1);.

• Calcule o interpolador usando a forma desejada.

• Avalia o polinômio encontrado nos pontos de interpolação x usando y2 = subs


(p,x);.

• Calcule o erro cometido usando [valor,posicao] = max(abs(y-y2)).

Veja o que ocorre quando n aumenta.


113

5 Ajuste de Curvas

No capítulo anterior tratamos do problema de encontrar um polinômio que aproxima


uma função (conhecida ou não). Este polinômio era escolhido de modo que ele passasse
por um conjunto de pontos previamente escolhidos da função.

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.

Figura 11 – Um interpolador não descreve bem os dados neste caso.

Esta alternativa é muito interessante do ponto de vista prático. Quando a quantidade


de dados é grande (1000 pontos) o polinômio terá uma enorme quantia de oscilações pois
será um polinômio de grau alto (999 para os 1000 pontos). Utilizar potências muito altas
de um valor pode causar diversos problemas numéricos, que já comentados no capítulo 1,
e deve ser evitado ao máximo.
114 Capítulo 5. Ajuste de Curvas

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.

Por essas razões, neste capítulo trataremos do seguinte problema:

“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.

5.1 Método dos Mínimos Quadrados


O método dos quadrados mínimos (também pode ser encontrado como mínimos
quadrados ou regressão linear/não-linear), baseia-se na ideia de definir uma noção de
distância entre funções e encontrar aquela que minimiza esta distância.

Construiremos aqui, para efeitos didáticos, o problema no caso em que a curva


desejada (também conhecida como modelo) é uma reta. O caso geral será comentado na
próxima seção e segue as mesmas ideias apresentadas aqui.

Considere a equação geral da reta1 :

y = ax + b. (5.1)

Estaremos interessados em determinar os coeficientes a e b de modo o modelo (5.1) descreva


os dados (pontos fornecidos) da melhor forma possível. Esta “melhor forma possível” será
explicada logo mais adiante.

Sejam (x1 , y1 ), ..., (xn , yn ), n pontos distintos e

ỹi = axi + b, i = 1, . . . , n.
1
Este será o nosso modelo.
5.1. Método dos Mínimos Quadrados 115

em que a e b são os coeficientes da reta que queremos determinar.

Definição 5.1 Definimos o desvio di de modelo em um ponto xi como a diferença entre


o valor do modelo neste ponto (que denotamos por ỹi ) e o valor real dos dados fornecidos
naquele ponto. Algebricamente:
di = yi − ỹi .

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.

Calculando as derivadas em relação a cada variável independente de d e igualando


a zero temos:
n

∂d
 ∂a (a, b) = −2 xi (yi − axi − b) = 0,

 X


i=1
n
∂d
(a, b) = −2 (yi − axi − b) = 0.

 X



∂b i=1

Organizando os termos, temos:


 n n n
x2i +b xi =
 X X X
a xi y i ,



i=1 i=1 i=1
n n
xi + bn =
 X X
a yi .



i=1 i=1

A expressão acima é um sistema linear 2 × 2 cuja as incógnitas são a e b. Matrici-


almente podemos escrever o método dos mínimos quadrados para o modelo y = ax + b:
 n
X
  n
X

 n xi  yi
 
b   
i=1
= X (5.2)
   i=1 
 n n
  n
.
 X  
2  a
X

xi xi

xi y i 
i=1 i=1 i=1

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
 

então o sistema linear pode ser escrito como

⇒ 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

i=1 i=1 i=1 i=1

Tendo estes quatro valores construímos o sistema linear:



10b + 55a = 81,

55b + 385a = 572.4.



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.

5.2 Caso Geral


Na seção anterior apresentamos a construção do método dos mínimos quadrados
para o caso no qual o modelo era uma reta. Porém, a técnica de regressão não está limitada
a este modelo. A construção do método no caso geral segue os mesmos passos apresentados,
isto é:

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

Figura 12 – Dados e modelo para o exemplo 5.1.

1. Definir o modelo;

2. Definir o desvio do modelo.

3. Derivar o desvio e igualar a zero.

4. Obter o sistema a ser resolvido.

No entanto, precisamos tomar cuidado no último passo. Isso porque, dependendo


do modelo, podemos não encontrar um sistema linear para resolver. Para entender isso,
precisamos diferenciar os modelos lineares e não-lineares. O mais importante, e que causa
mais confusões, é não pensar que um modelo linear é o mesmo que o modelo ser uma reta.

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.

Seguindo a definição acima podemos concluir que o modelo y = ax + b é linear pois


(5.2) é um sistema linear. Porém, veremos a seguir que ele não é o único possível.

Exemplo 5.2 Considere o modelo y = ax2 + bx + c. Seguindo os passos do método


5.2. Caso Geral 119

encontraremos o sistema linear


 n n   n 
x2i
X X X
 n xi 
 
 yi 
 i=1 i=1
 c   i=1

n n n n
   
    
x2i 3 
= (5.5)
X X X X

 xi xi   b 
 
 xi y i 
.
    
i=1 i=1 i=1 i=1
n n n n
    
 
a  
x2i x3i 4  2
X X X X

xi 
xy 
i i
i=1 i=1 i=1 i=1

Assim, apesar do modelo não ser uma reta, o modelo é linear.

Exemplo 5.3 Considere o modelo y = aex + b. Novamente, seguindo os passos do método


encontraremos o sistema linear
 n   n 
xi
X X
n e yi
 
 
b   
i=1
= (5.6)
   i=1 
 n n
 n
.
 X   X 
exi 2xi  a e xi y i
X

e  
i=1 i=1 i=1

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.

Os modelos não-lineares têm seu lugar ao sol quando pensamos em aplicações


práticas. Porém, exigem um tratamento mais cuidadoso com outras ferramentas (como é o
caso do método de Newton visto no capítulo 2 na versão para dimensões maiores que 1).
Neste texto estamos interessados apenas em identificar se um dado modelo é linear ou não
e tratar dos casos 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

para o modelo com a exponencial.

Ou seja, a matriz A muda de acordo com o modelo (assim como o vetor de


coeficientes), mas o formato geral é preservado. Assim, se quisermos usar o modelo
y = ax3 + bx2 + cx + d, não precisamos fazer toda a construção do método desde o início.
Basta sabermos que a matriz A e o vetor de coeficientes neste caso serão:
   
1 x1 x21 x31   d 
 
1
 
x2 x22 x32 
 
 c 
 
A= , v= .
 
. .. .. .. 
.  
. . . . b
  
   
 
1 xn x2n x3n
 
a

Observação 5.3 É importante tomarmos o cuidado de coincidir os coeficientes na ordem


correta na qual eles aparecem na matriz e vice-versa.

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.

5.3.1 Primeira forma

A ideia desta forma é seguir os passos do exemplo 5.1. Ou seja, calcular os 4


somatórios, construir o sistema linear e resolvê-lo.

O código abaixo segue o modelo em 8.22 para calcular os somatórios de forma


manual (e menos eficiente). Note que não é necessário utilizar um for para cada somatório.
As linhas 22 − 24 são responsáveis por construir e resolver o sistema (5.2).

Código 5.1 – Método dos mínimos quadrados - primeira forma.


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 = 0;
122 Capítulo 5. Ajuste de Curvas

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

14 somax2 = sum ( x .^2) ;


15
16 B = [ n somax ; somax somax2 ];
17 rhs = [ somay ; somaxy ];
18 coef = B \ rhs ;

5.3.2 Segunda forma

A ideia da segunda forma consiste em construir a matriz A e resolver o sistema na


forma matricial (5.3). O MATLAB permite que façamos isso de forma muito eficiente.

A matriz A possui n linhas e 2 colunas. Na primeira coluna todas as componentes


são iguais a 1, para construí-las utilizamos a function ones, veja 8.5 sobre ela. Na segunda
coluna temos as abscissas dos dados, que estará na variável x.

Assim, a construção da matriz A pode ser feita em apenas uma linha:

1 A = [ ones (n ,1) x ];

em que n precisa estar definida previamente.

Tendo a variável A definida, basta então resolver o sistema linear (5.4) usando a
barra “\”:

1 coef = (A '* A ) \( A '* y ) ;

O código completo fica:

Código 5.3 – Método dos mínimos quadrados - segunda forma.


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 )
124 Capítulo 5. Ajuste de Curvas

9
10 n = length ( x ) ;
11 A = [ ones (n ,1) x ];
12 coef = (A '* A ) \( A '* y ) ;

5.3.3 Basic Fitting

Uma terceira forma de aplicar o método dos mínimos quadrados em um conjunto


de dados é através da ferramenta de basic fitting do MATLAB. Você pode plotar os dados
e acessar a ferramenta através da barra superior da janela de figura ou usar utilizar a
function polyfit. Veja a documentação dela para compreender o seu uso.

O código abaixo é um exemplo simples de regressão adaptado da documentação do


MATLAB.

1 % Cria um conjunto de dados .


2 x = 1:50;
3 y = -0.3* x + 2* randn (1 ,50) ;
4
5 % Calcula o modelo de regressao usando um polinômio de grau
1.
6 p = polyfit (x ,y ,1) ;
7
8 % Avalia o modelo nos pontos e plota .
9 f = polyval (p , x ) ;
10 plot (x ,y , 'o ' ,x ,f , ' - ')
11 legend ( ' data ' , ' linear fit ')
5.4. Exercícios 125

5.4 Exercícios

1. Escreva com detalhes a construção do método dos mínimos quadrados para os


modelos abaixo:

a) y = ax2 + bx + c;

b) y = a sen(x) + b cos(x);

c) y = ax2 + by 2 + cxy;

2. Ajuste os dados da tabela abaixo usando o um polinômio de grau adequado (escolha


baseado no gráfico).

xi -2 -1 0 1 2
yi 6 2 -1 1 4

3. Escreva um script no MATLAB para resolver a questão anterior.

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

Resposta: z = (13x + y + 8)/9.

7. Implemente o método dos mínimos quadrados para o modelo da questão anterior.


Caso consiga, plote os pontos e o plano para visualizar sua resposta.

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

a) Obtenha uma estimativa para a população brasileira no ano de 2000. Escolha o


grau do polinômio que achar mais conveniente para os dados.

b) Pesquise na internet e verifique a precisão da sua estimativa.

c) Em que ano a população brasileira ultrapassou o índice de 100 milhões? Utilize


o ajuste para encontrar essa estimativa.

OBS: Faça esta questão usando o MATLAB.

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

No cálculo de funções de uma variável real estudamos as funções integráveis e


aprendemos algumas técnicas para calcular primitivas. Em particular, se f (x) é uma
função contínua em [a, b], então esta função tem uma antiderivada (ou primitiva) nesse
intervalo, isto é, existe uma função F (x) tal que F 0 (x) = f (x).

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

Em muitos problemas reais é muito comum a necessidade do cálculo de integrais


definidas de funções que conhecemos apenas em alguns pontos (por exemplo quando essas
informações são advindas de experimentos ou medições) ou que simplesmente não possui
uma primitiva conhecida (por exemplo quando ela é definida como uma combinação de
diversas outras funções).

Com isso em mente, nosso problema neste capítulo será:

“Dada uma função f contínua definida em um intervalo [a, b], apro-


Z b
ximar o valor de f (x) dx.”
a

As técnicas que veremos neste capítulo são chamadas de métodos de integração


numérica ou quadratura. As duas regras de quadratura que veremos fazem uso dos
polinômios interpoladores que vimos no capítulo 4. Vamos aproximar a função f pelo
interpolador e integrá-lo.

Além da classe de métodos que veremos aqui, um conjunto importantíssimo de


métodos de integração numérica chama-se quadratura de Gauss, ou quadratura gaussiana.

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).

Pensando em polinômios interpoladores, podemos ver que na figura 13, em cada


intervalo, o que estamos fazendo na verdade é calcular a integral do polinômio interpolador
128 Capítulo 6. Integração Numérica

Figura 13 – Soma de Riemann usando interpolador de grau 0.

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.

Os métodos que veremos consistem simplesmente em melhorar essa aproximação


usando polinômios de grau 1 (regra dos trapézios) e 2 (regra de Simpson 1/3). Em cada
um destes métodos, primeiro iremos apresentar a regra na forma “simples” usando apenas
um polinômio e depois a forma “generalizada” para n subintervalos.

6.1 Regra dos Trapézios


Seja f (x) uma função definida no intervalo [a, b]. A regra dos trapézios consiste
em utilizar o polinômio interpolador de grau 1 para aproximar f no intervalo [a, b] e, com
isso, aproximar o valor da integral de f pelo valor da integral do interpolador.

Como visto no capítulo 4, para calcular um polinômio de grau 1 precisamos de 2


pontos. Vamos considerar os pontos x0 = a e x1 = b e denotar o comprimento do intervalo
por h = x1 − x0 .

Da forma de Lagrange para o polinômio p1 (x) que interpola f (x) em x0 e x1 temos

(x − x1 ) (x − x0 )
p1 (x) = f (x0 ) + f (x1 ) =
(x0 − x1 ) (x1 − x0 )

(x − x1 ) (x − x0 )
= f (x0 ) + f (x1 ) .
−h h

A figura 14 esboça uma função f qualquer e o interpolador p1 . Como é possível ver,


o interpolador de grau 1 é uma reta e a região abaixo do seu gráfico é sempre um trapézio.
6.1. Regra dos Trapézios 129

Portanto, não é necessário calcular a integral de p1 explicitamente pois ela é equivalente a


área do trapézio de bases f (x0 ) e f (x1 ) e altura h.

Figura 14 – Visualização da regra do trapézio simples.

Assim, a integral de f no intervalo [a, b] = [x0 , x1 ] pode ser aproximada por:


Z b Z x1
f (x) dx ≈ p1 (x)dx
a x0

Z x1 "
(x − x1 ) (x − x0 )
#
= f (x0 ) + f (x1 ) dx
x0 −h h

= Área do Trapézio

h
= [f (x0 ) + f (x1 )]
2

Então, a regra do trapézio simples é definida como


Z b
h
f (x) dx ≈ [f (x0 ) + f (x1 )]. (6.1)
a 2

Exemplo 6.1 Problema: Calcule o valor aproximado de 0,5 (ln x + x)dx usando a Regra
R1

dos Trapézios.

Solução: Temos f (x) = ln x + x, x0 = 0.5 e x1 = 1.0. Portanto,

h = 0.5, f (x0 ) = −0.1931, f (x1 ) = 1.0.

Substituindo em (6.1) temos


Z 1
h
(ln x + x) dx ≈ [f (x0 ) + f (x1 )] = 0.25 × 0.8069 = 0.2017.
0.5 2

A função f possui primitiva e, portanto, é possível comparar a solução aproximada


encontrada com a solução exata. Neste caso, a integral exata é igual a 0.2215.
130 Capítulo 6. Integração Numérica

A Regra dos Trapézios Generalizada consiste em dividir o intervalo de integração


xn − x0
[a, b] em n subintervalos iguais1 , cada qual de amplitude h = , com x0 = a e
n
xn = b, e aplicarmos a Regra dos Trapézios em cada subintervalo. A figura 15 esboça estas
informações.

Figura 15 – Visualização da regra dos trapézios generalizada.

Somando a regra do trapézio simples aplicada a cada um destes intervalos temos a


regra dos trapézios generalizada:
Z xn
h h
f (x)dx ≈ [f (x0 ) + f (x1 )] + . . . + [f (xn−1 ) + f (xn )]
x0 2 2

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.

Solução: Primeiramente, como é pedido que usemos 6 subintervalos, temos n = 6.


Os extremos do intervalo são a = 1 e b = 4, portanto,

b−a 4−1 1
h= = = .
n 6 2

Começando em x0 = a e indo até x6 = b temos os seguintes pontos:


1
Na prática esses subintervalos não precisam ter o mesmo tamanho, mas vamos fazer apenas esta caso
por simplicidade pois é o mais comum.
6.1. Regra dos Trapézios 131

xi 1 1.5 2 2.5 3 3.5 4


f (xi ) 1.0000 1.2247 1.4142 1.5811 1.7321 1.8708 2.0000

Agora, basta substituir na expressão (6.2):


Z 4√
h
x dx ≈ [f (x0 ) + 2f (x1 ) + 2f (x2 ) + 2f (x3 ) + 2f (x4 ) + 2f (x5 ) + f (x6 )] =
1 2
0.5
= (1.0000 + 2 × 1.2247 + 2 × 1.4142 + 2 × 1.5811+
2

+ 2 × 1.7321 + 2 × 1.8708 + 2.0000) = 4.6615.


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

Assim como os métodos de interpolação e ajuste, as regras de integração não são


métodos iterativos. De fato, tudo que precisamos para implementar a regra dos trapézios
generalizada é fazer um somatório como em 8.22.

Existem diversas formas de implementar este somatório a partir de (6.2). Aqui


iremos apresentar algumas, mas você é encorajado a tentar outras formas.

Primeiramente, existem duas possibilidades de variáveis de entrada:

• A função f , os extremos do intervalo a e b e o número de subintervalos n: nesta caso,


calculamos h, os pontos xi e yi = f (xi ) dentro da function.

• Os vetores x e y com as abscissas e o valor da função f avaliada em x: neste caso,


calculamos h = x1 − x0 e n = length(x)-1; dentro da function.

Aqui iremos optar por fazer da segunda forma. Deixamos assim a tarefa de definir os
pontos e avaliar a função para o script.

Observação 6.1 É mais comum implementarmos passando n como variável na primeira


forma ao invés de passar h como variável de entrada, pois evita casos do tipo a = 0, b = 1
e h = 0.3, isto é, n seria um número não inteiro.
132 Capítulo 6. Integração Numérica

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

Definindo m = length(x); e h = x(2)- x(1), calculamos o somatório acima


usando o código:

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.

Código 6.1 – Regra dos trapézios - primeira forma.


1 % DESCRICAO : Implementacao da regra dos trapezios
generalizada .
2 %
3 % ENTRADA :
4 % x - Abscissas dos pontos .
5 % y - Ordenadas dos pontos . y ( i ) = f ( x ( i ) ) .
6 % SAIDA :
7 % I - Aprox da integral .
8 function I = regraTrap1 (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 = 0;
6.1. Regra dos Trapézios 133

16 for i = 1: m -1
17 I = I + ( y ( i ) + y ( i +1) ) ;
18 end
19 I = I * h /2;

A segunda forma de implementar este método seria usando a expressão:


Z xn
h
f (x)dx ≈ [f (x0 ) + 2f (x1 ) + 2f (x2 ) + · · · + 2f (xn−1 ) + f (xn )] =
x0 2
n−1
h
= (f (x0 ) + f (xn )) + h f (xi )
X
2 i=1

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.

Código 6.2 – Regra dos trapézios - segunda forma.


1 % DESCRICAO : Implementacao da regra dos trapezios
generalizada .
2 %
3 % ENTRADA :
4 % x - Abscissas dos pontos .
5 % y - Ordenadas dos pontos . y ( i ) = f ( x ( i ) ) .
6 % SAIDA :
7 % I - Aprox da integral .
8 function I = regraTrap2 (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 = h *( y (1) + y ( m ) ) /2;
134 Capítulo 6. Integração Numérica

16 for i = 2: m -1
17 I = I + h*y(i);
18 end

Código 6.3 – Regra dos trapézios - terceira forma.


1 % DESCRICAO : Implementacao da regra dos trapezios
generalizada .
2 %
3 % ENTRADA :
4 % x - Abscissas dos pontos .
5 % y - Ordenadas dos pontos . y ( i ) = f ( x ( i ) ) .
6 % SAIDA :
7 % I - Aprox da integral .
8 function I = regraTrap3 (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 = 0;
16 for i = 2: m -1
17 I = I + y(i);
18 end
19 I = h * I + h *( y (1) + y ( m ) ) /2;

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

perceber facilmente o quão ineficiente esta forma é em relação as anteriores (fazemos


diversos testes if que não são realmente necessários).

Código 6.4 – Regra dos trapézios - quarta forma.


1 % DESCRICAO : Implementacao da regra dos trapezios
generalizada .
2 %
3 % ENTRADA :
4 % x - Abscissas dos pontos .
5 % y - Ordenadas dos pontos . y ( i ) = f ( x ( i ) ) .
6 % SAIDA :
7 % I - Aprox da integral .
8 function I = regraTrap4 (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 = 0;
16 for i = 1: m
17 if i == 1 || i == m
18 I = I + y(i);
19 else
20 I = I + 2* y ( i ) ;
21 end
22 end
23 I = ( h /2) * I ;

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

Código 6.5 – Regra dos trapézios - forma vetorizada.


1 % DESCRICAO : Implementacao da regra dos trapezios
generalizada .
2 %
3 % ENTRADA :
4 % x - Abscissas dos pontos .
5 % y - Ordenadas dos pontos . y ( i ) = f ( x ( i ) ) .
6 % SAIDA :
7 % I - Aprox da integral .
8 function I = regraTrapVet (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 = h *( y (1) + y ( m ) ) /2 + h * sum ( y (2: m -1) ) ;

O script a seguir apresenta de forma bem simplificada que todas as formas apre-
sentadas coincidem.

1 % Script para testar todas as formas de implementar a regra


dos trapezios .
2
3 a = 1; % Limite interior do intervalo .
4 b = 4; % Limite interior do intervalo .
5 n = 6; % Numero de subintervalos .
6 h = (b - a ) / n ; % Passo .
7 f = @( x ) ( sqrt ( x ) ) ; % Integrando .
8
9 x = ( a : h : b ) ';
10 y = f ( x ) ;
11
12 I1 = regraTrap1 (x , y ) % Primeira forma .
6.2. Regra 1/3 de Simpson 137

13 I2 = regraTrap2 (x , y ) % Segunda forma .


14 I3 = regraTrap3 (x , y ) % Terceira forma .
15 I4 = regraTrap4 (x , y ) % Quarta forma .
16 IVet = regraTrapVet (x , y ) % Forma vetorizada .

6.2 Regra 1/3 de Simpson


Seguindo a ideia das construções feitas para a regra dos trapézios, vamos usar a
forma de Lagrange para estabelecer a fórmula de integração resultante da aproximação de
f (x) por um polinômio de grau 2.

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.

Seja p2 (x) o polinômio que interpola f (x) nos pontos x0 = a, x1 = x0 + h e


x2 = x0 + 2h = b como na figura 16. Note que aqui h = (b − a)/2. Do capítulo 4 temos

(x − x1 )(x − x2 ) (x − x0 )(x − x2 ) (x − x0 )(x − x1 )


p2 (x) =f (x0 ) + f (x1 ) + f (x2 )
(x0 − x1 )(x0 − x2 ) (x1 − x0 )(x1 − x2 ) (x2 − x0 )(x2 − x1 )

(x − x1 )(x − x2 ) (x − x0 )(x − x2 ) (x − x0 )(x − x1 )


= f (x0 ) + f (x1 ) + f (x2 )
(−h)(−2h) h(−h) (2h)h

(x − x1 )(x − x2 ) (x − x0 )(x − x2 ) (x − x0 )(x − x1 )


= f (x0 ) − f (x1 ) + f (x2 ) .
2h 2 h 2 2h2

Aproximando f pelo polinômio interpolador p2 podemos aproximar o valor da


integral de f no intervalo [a, b]:

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

Figura 16 – Esboço do interpolador de grau 2 para a forma de Simpson.

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.

Fazendo a mudança de variáveis z = (x − x0 )/h temos

dx
x − x0 = zh ⇒ x = x0 + zh ⇒ = h ⇒ dx = hdz.
dz

Os termos que aparecem no integrando ficam:

x − x0 = zh,

x − x1 = x − (x0 + h) = x − x0 − h = zh − h = h(z − 1),

x − x2 = x − (x0 + 2h) = x − x0 − 2h = zh − 2h = h(z − 2),

e os limites de integração serão:

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

Com essas mudanças temos:


f (x0 ) Z x2 f (x0 ) Z 2
(x − x 1 )(x − x 2 )dx = (z − 1)h(z − 2)hhdz
2h2 x0 2h2 0

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

Os integrandos resultantes são polinômios de grau 2 e podem ser facilmente


integrados:
f (x0 )h Z 2 f (x0 )h 2 1
 
(z − 1)(z − 2)dz = = f (x0 )h
2 0 2 3 3
Z 2
−4 4
 
f (x1 )h z(z − 2)dz = f (x1 )h = − f (x1 )h
0 3 3

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.

Solução: A primeira coisa que precisamos lembrar é como calcular o h correta-


mente. Mesmo sendo a versão simples precisamos de dois intervalos pois é necessário três
pontos. Assim,
b−a 1, 5 − 0, 5 1
h= = = .
2 2 2
Os pontos que usaremos e o valor da função f (x) = cos(x) neles são:
2
A expressão da regra explica o “1/3” no nome.
140 Capítulo 6. Integração Numérica

xi 0, 5 1, 0 1, 5
f (xi ) 0, 8776 0, 5403 0, 0707

Aplicando a fórmula (6.3) obtemos:


Z 1,5
h
cos x dx ≈ [f (x0 ) + 4f (x1 ) + f (x2 )] =
0,5 3

0, 5
= (0, 8776 + 4 × 0, 5403 + 0, 0707) = 0, 5183.
3

A título de comparação, o valor exato (usando 4 casas decimais) da integral é


0, 5181.

A generalização da regra de Simpson 1/3 é razoavelmente simples. Para isso,


subdividirmos o intervalo de integração [a, b] em n subintervalos de tamanho h de forma
que x0 = a e xn = b e aplicarmos a regra 1/3 de Simpson em cada 2 subintervalos
consecutivos. É importante perceber que o número de intervalos n precisa ser par para
que isso seja possível.

Assim, a regra de Simpson 1/3 generalizada é:


Z b
h h
f (x) dx ≈ [f (x0 ) + 4f (x1 ) + f (x2 )] + · · · + [f (xn−2 ) + 4f (xn−1 ) + f (xn )]
a 3 3
h
= [f (x0 ) + 4f (x1 ) + 2f (x2 ) + 4f (x3 ) + · · · + 2f (xn−2 ) + 4f (xn−1 ) + f (xn )]. (6.4)
3

Note que na expressão acima temos o valor de f nas extremidades multiplicado


por 1 e nos pontos interiores alternamos coeficientes 4 e 2, sendo que 4 é o primeiro e o
último sempre.

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.

Solução: Como a = 0, b = 3 e n = 6 temos h = (b − a)/n = 1/2. Os sete pontos


e o valor de f (x) = xex + 1 são dados na tabela abaixo.

xi 0 0.5 1 1.5 2 2.5 3


f (xi ) 1.0000 1.8244 3.7183 7.7225 15.7781 31.4562 61.2566
6.2. Regra 1/3 de Simpson 141

Substituindo em (6.4) obtemos a aproximação pela regra de Simpson 1/3 generali-


zada:

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

+ 4 × 31.4562 + 61.2566) = 44.2103.

O valor exato da integral é 44.1711.

Antes de passarmos para a implementação é importante ressaltar uma informação


sobre o erro cometido na aproximação. Pensando no erro absoluto entre o valor exato e o
valor aproximado encontrado nos quatro exemplos apresentados, é possível perceber que a
regra de Simpson 1/3 simples foi a que obteve menor erro de aproximação. Isso não faz
muito sentido se pensarmos que estamos fazendo a forma generalizada (que exige mais
esforço computacional) justamente para ter uma aproximação melhor.

O problema está no fato que estamos comparando problemas diferentes. Em cada


um dos exemplos utilizou-se integrandos diferentes. No final das contas, um fator que
influencia diretamente no erro cometido é o comportamento da função que está sendo
integrada. Quando mais “bem comportada” (como é o caso de f (x) = cos(x)) ela for
menor o esforço necessário para obter um erro menor. Já funções “má comportadas” (como
f (x) = xex + 1) precisam de métodos melhores ou mais pontos para obter um erro tão
pequeno quanto o obtido para as bem comportadas.

Via de regra, a menos de erros numéricos, a regra de Simpson 1/3 (generalizada ou


simples) obterá um erro menor que a regra dos trapézios. Isso ocorre simplesmente porque
no regra de Simpson usamos um conjunto maior de polinômio (grau menor ou igual a 2) e
que contém aqueles disponíveis para a regra dos trapézio (grau menor ou igual a 1).

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.

Se pensarmos de forma direta na expressão (6.4) recairemos em algo semelhante a


quarta forma apresentada para a regra dos trapézios onde usamos uma condição de seleção
if dentro da somatória. Veja abaixo como o código fica.

Código 6.6 – Regra de Simpson 1/3 - primeira forma.


1 % DESCRICAO : Implementacao da regra de Simpson 1/3
generalizada .
2 %
3 % ENTRADA :
4 % x - Abscissas dos pontos .
5 % y - Ordenadas dos pontos . y ( i ) = f ( x ( i ) ) .
6 % SAIDA :
7 % I - Aprox da integral .
8 function I = regraSimp1 (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: m -1
17 if mod (i ,2) == 0 % indices pares sao multiplicados por 4.
18 I = I + 4* y ( i ) ;
19 else
20 I = I + 2* y ( i ) ;
21 end
22 end
23 I = I * h /3;
6.2. Regra 1/3 de Simpson 143

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

A segunda forma de implementar a regra de Simpson 1/3 é possível reescrevendo a


expressão (6.4) separando aqueles multiplicados por 4 e aqueles multiplicados por 2:
 
Z b n/2 (n/2)−1
h
f (x) dx ≈ f (x0 ) + f (xn ) + 4 f (x2i−1 ) + 2 f (x2i ) .
X X
a 3 i=1 i=1

Ou seja, separamos a expressão em dois somatórios com passo 2 no loop do for.


Assim, somamos primeiro uma parte e depois a outra como no código abaixo.

Código 6.7 – Regra de Simpson 1/3 - segunda forma.


1 % DESCRICAO : Implementacao da regra de Simpson 1/3
generalizada .
2 %
3 % ENTRADA :
4 % x - Abscissas dos pontos .
5 % y - Ordenadas dos pontos . y ( i ) = f ( x ( i ) ) .
144 Capítulo 6. Integração Numérica

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).

Código 6.8 – Regra de Simpson 1/3 - terceira forma.

1 % DESCRICAO : Implementacao da regra de Simpson 1/3


generalizada .
2 %
3 % ENTRADA :
4 % x - Abscissas dos pontos .
5 % y - Ordenadas dos pontos . y ( i ) = f ( x ( i ) ) .
6 % SAIDA :
7 % I - Aprox da integral .
8 function I = regraSimp3 (x , y )
9
10 % n = numero de subintervalos .
6.2. Regra 1/3 de Simpson 145

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 = 1:(( m -1) /2)
17 I = I + 4* y (2* i ) ;
18 end
19 for i = 2:(( m -1) /2)
20 I = I + 2* y (2* i -1) ;
21 end
22 I = I * h /3;

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;

A quinta forma de possível é somar os termos seguindo a expressão:


Z b
h h
f (x) dx ≈ [f (x0 ) + 4f (x1 ) + f (x2 )] + · · · + [f (xn−2 ) + 4f (xn−1 ) + f (xn )].
a 3 3

Neste caso, temos apenas um somatório com passo 2. O código fica como abaixo.

Código 6.9 – Regra de Simpson 1/3 - quinta forma.


1 % DESCRICAO : Implementacao da regra de Simpson 1/3
generalizada .
2 %
3 % ENTRADA :
3
De fato, como o número de subintervalos n é par, o número de pontos será sempre ímpar. Removendo
as duas extremidades, nos resta uma quantia de pontos ímpares.
146 Capítulo 6. Integração Numérica

4 % x - Abscissas dos pontos .


5 % y - Ordenadas dos pontos . y ( i ) = f ( x ( i ) ) .
6 % SAIDA :
7 % I - Aprox da integral .
8 function I = regraSimp5 (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 = 0;
16 for i = 1:2: m -2
17 I = I + ( y ( i ) + 4* y ( i +1) + y ( i +2) ) ;
18 end
19 I = I * h /3;

Por fim, apresentamos a forma vetorizada da implementação, que utiliza a function


sum para somar os termos.

Código 6.10 – Regra de Simpson 1/3 - forma vetorizada.

1 % DESCRICAO : Implementacao da regra de Simpson 1/3


generalizada .
2 %
3 % ENTRADA :
4 % x - Abscissas dos pontos .
5 % y - Ordenadas dos pontos . y ( i ) = f ( x ( i ) ) .
6 % SAIDA :
7 % I - Aprox da integral .
8 function I = regraSimpVet (x , y )
9
10 % n = numero de subintervalos .
11 m = length ( x ) ; % Numero de pontos .
6.2. Regra 1/3 de Simpson 147

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.

1 % Script para testar todas as formas de implementar a regra


dos trapezios .
2
3 a = 1; % Limite interior do intervalo .
4 b = 4; % Limite interior do intervalo .
5 n = 6; % Numero de subintervalos .
6 h = (b - a ) / n ; % Passo .
7 f = @( x ) ( sqrt ( x ) ) ; % Integrando .
8
9 x = ( a : h : b ) ';
10 y = f ( x ) ;
11
12 I1 = regraSimp1 (x , y ) % Primeira forma .
13 I2 = regraSimp2 (x , y ) % Segunda forma .
14 I3 = regraSimp3 (x , y ) % Terceira forma .
15 I4 = regraSimp4 (x , y ) % Quarta forma .
16 I5 = regraSimp5 (x , y ) % Quinta forma .
17 IVet = regraSimpVet (x , y ) % Forma vetorizada .
148 Capítulo 6. Integração Numérica

6.3 Exercícios

1. Aplique as regras do trapézio e Simpson 1/3 com n = 6 para todos os exemplos


deste capítulo.

2. Compare a solução exata e a aproximação da regra do trapézio simples (n = 1) e a


Z 2
da regra de 1/3 de Simpson simples (n = 2)para a integral f (x) dx quando f (x)
0
é:
a) x2 b) x4 c) (x + 1)−1

d) 1 + x2 e) sin x f) ex

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

3. No item a) da questão anterior o resultado do método de Simpson 1/3 coincidiu com


a solução exata. Por quê?

4. Resolva os itens c), d) e e) da questão anterior utilizando as regras dos Trapézios e


de Simpson generalizadas com n = 4 subintervalos. Compare os resultados obtidos
com a solução exata.

5. Resolva os itens c), d) e e) da questão anterior utilizando as regras dos Trapézios e


de Simpson generalizadas com n = 8 subintervalos. Compare os resultados obtidos
com a solução exata.

6. Escreva um script para verificar a resposta das questões que você fez em papel.

7. Determinar a seção reta de rios e lagos é importante em projetos de prevenção de


enchentes (para o cálculo de vazão da água) e nos cálculos de reservatório (para o
cálculo do volume total de água). A menos que dispositivos tipo sonar sejam usados
na obtenção do perfil de rios/lagos, o engenheiro civil deve trabalhar com valores de
profundidade obtidos em pontos discretos da superfície. A tabela abaixo mostra um
exemplo típico de perfil de profundidade.
6.3. Exercícios 149

Distância da margem (m) 0 2 4 6 8 10 12 14 16 18 20


Profundidade (m) 0.0 1.8 2.0 4.0 4.0 6.0 4.0 3.6 3.4 2.8 0.0
Utilize a regra de Simpson para aproximar a área da seção reta. Escreva um script
para resolver este problema usando os métodos estudados.

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

Escreva um código para aproximar a distância percorrida pelo automóvel.


151

7 Equações Diferenciais Ordinárias

As equações diferenciais ordinárias (EDO) surgem naturalmente nas mais diversas


áreas de pesquisa das ciências exatas. Por exemplo, efeitos ondulatórios, análises estruturais,
estudo de reações químicas e previsão de trajetórias balísticas e de satélites artificiais.

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.

Pensando nisso, nosso problema neste capítulo será:

“Dada um problema de valor inicial (PVI):




 y 0 = f (x, y)
(7.1)
y(x0 ) = y0

construir x1 , x2 , . . . xn igualmente espaçados e calcular aproximações


yi ≈ y(xi ) nestes pontos usando xi−1 e yi−1 .”

Ou seja, iremos aproximar o valor da solução exata y do PVI (7.1) em um conjunto


de pontos equidistantes.

Em um curso comum de EDOs nos limitamos a estudar as técnicas para EDOs


lineares. O problema (7.1) é mais abrangente que isso pois engloba também as equações
não lineares. Por exemplo, a EDO y 0 = y 2 + sen(xy) não pode ser resolvida analiticamente
usando as técnicas clássicas, mas poderemos aproximar sua solução numericamente.

É 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.

Apresentamos aqui três métodos:

• Método de Euler (mais simples e menos preciso);

• Método de Runge-Kutta de segunda ordem (qualidade intermediária);

• Método de Runge-Kutta de quarta ordem (melhor qualidade);


152 Capítulo 7. Equações Diferenciais Ordinárias

O método de Euler, apesar de menos preciso, é muito útil quando a solução


procurada é sabidamente suave. Além disso, é frequentemente utilizado nos métodos
numéricos para aproximar solução de equações diferenciais parciais (que não trataremos
nesta apostila), sendo aplicado na variável temporal.

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.

7.1 Método de Euler


O método de Euler é o mais simples para aproximação de solução de PVI. A estra-
tégia dele consiste em fazer aproximações lineares em cada ponto, dado que a declividade
da solução em qualquer ponto é dado pela própria EDO.

Faremos a construção do método de duas formas diferentes. Na primeira usamos a


série de Taylor da solução e na segunda faremos através da equação da reta tangente.

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!

para qualquer h > 0. Aqui, y (n) denota a derivada de ordem n de y.

Se truncarmos a série de Taylor de y no segundo termo (que envolve a derivada de


primeira ordem) e denotando por x1 = x0 + h, obtemos:

y(x1 ) ≈ y(x0 ) + h y 0 (x0 )

Agora, de (7.1) temos que y 0 (x0 ) = f (x0 , y0 ) e y(x0 ) = y0 . Portanto, podemos


definir:
y1 = y0 + h f (x0 , y0 )

em que y1 é uma aproximação para y(x1 ).


7.1. Método de Euler 153

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 .

Repetindo o processo acima no ponto x1 podemos obter uma aproximação y2 ≈ y(x2 )


em que x2 = x1 + h = x0 + 2h.

De modo geral, o método de Euler é dado pela expressão:

yi+1 = yi + hf (xi , yi ), i = 0, 1, 2, . . . (7.2)

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 ).

Agora, se tomarmos x = x1 = x0 + h, para algum valor de h fixo, teremos:

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).

Exemplo 7.1 Problema: Aproxime a solução do PVI abaixo com h = 0, 2:




 y 0 = 2xy, x ∈ [1, 2]
y(1) = 3,

Solução: Como h = 0, 2, x0 = 1 e xn = 2, então os 6 pontos onde iremos


aproximar a solução serão x = (x0:h:xn)';. Usando y0 = 3 e f (x, y) = 2xy fazemos:

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.

Para os demais pontos temos:

y(1, 4) ≈y2 = y1 + h f (x1 , y1 ) = 4, 2 + 0, 2 × (2 × 1, 2 × 4, 2) = 6, 216

y(1, 6) ≈y3 = y2 + h f (x2 , y2 ) = 6, 216 + 0, 2 × (2 × 1, 4 × 6, 216) = 9, 697

y(1, 8) ≈y4 = y3 + h f (x3 , y3 ) = 9, 697 + 0, 2 × (2 × 1, 6 × 9, 697) = 15, 9031

y(2, 0) ≈y5 = y4 + h f (x4 , y4 ) = 15, 9031 + 0, 2 × (2 × 1, 8 × 15, 9031) = 27, 3533

A solução exata deste PVI é y(x) = 3ex . A tabela e a figura abaixo resumem os
2 −1

resultados obtidos:

xi y(xi ) yi Err. Rel.


1 3 3 0
1.2 4.6581 4.2 0.09835
1.4 7.8351 6.216 0.20665
1.6 14.276 9.697 0.32077
1.8 28.18 15.903 0.43566
2 60.257 27.353 0.54606

É possível perceber que o método aproxima razoavelmente bem a solução no início,


porém no final a aproximação fica consideravelmente distante da solução exata. Este efeito
de “piorar cada vez mais” é comum e bem visível quando a solução exata é somente
crescente ou decrescente.

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.

Uma alternativa às variáveis de entrada listadas seria passar o vetor x já calculado


previamente. Não apresentamos esta implementação aqui mas você não deve ter problema
em fazê-la.

Com as variáveis de entrada definidas precisamos calcular e declarar alguns termos.


Primeiro, declaramos h = (xn-x0)/n; e o vetor de pontos nos quais encontraremos as
aproximações x = (x0:h:xn)';. Depois disto fazemos a pré-alocação da variável y para
que ela não troque de dimensão a cada passo do loop. Para isso, fazemos y = zeros(n
+1,1);, lembrando que se temos n passos temos n+1 pontos. Note que com isso as variáveis
x e y tem a mesma dimensão. Por fim, atribuímos o primeiro valor do vetor y que já é
conhecido, isto é, y0.

Isso conclui a implementação do método. Abaixo apresentamos a versão final deste


código.

Código 7.1 – Método de Euler.


1 % DESCRICAO : Implementacao do metodo de Euler .
2 %
156 Capítulo 7. Equações Diferenciais Ordinárias

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

7.2 Método de Runge-Kutta de 2ª ordem


Os métodos de Runge-Kutta formam uma classe de métodos de alta ordem para
aproximar a solução de EDOs. Como é usual na maioria das bibliografias, aqui apresentamos
um dos métodos de segunda ordem (que é um pouco melhor que o método de Euler) e um
dos métodos de quarta ordem (que é muito melhor que os anteriores).

A base teórica dos métodos de Runge-Kutta é a teoria de integração numérica. O


método de Euler poderia ter sido construído usando a regra de integração numérica com
polinômio interpolador de ordem 0 da seguinte forma: se y 0 = f (x, y) então, integrando no
intervalo [x0 , x1 ] temos
Z x1
y(x1 ) − y(x0 ) = f (x, y(x)) dx ≈ hf (x0 , y0 ).
x0
7.2. Método de Runge-Kutta de 2ª ordem 157

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.

Não apresentaremos a construção destes métodos aqui. Nos limitaremos a apresentar


as suas expressões e aplicá-las. O método de Runge-Kutta de segunda ordem (RK2) é:

k1 = h f (xi , yi )






k2 = h f (xi + h2 , yi + 21 k1 ) (7.3)



yi+1 = yi + k2


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.

Exemplo 7.2 Problema: Aproximar o exemplo apresentado no método de Euler usando


o método de Runge-Kutta de segunda ordem.

Solução: Como temos o mesmo problema do método de Euler, os pontos xi serão


os mesmos. Para calcular a aproximação pelo método de Runge-Kutta calculamos k1 , depois
k2 e por fim o novo yi+1 :

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

Para os demais pontos temos:

k1 = h f (x1 , y1 ) = 0, 2 × 11, 0016 = 2, 20032

k2 = h f (x1 + h/2, y1 + k1 /2) = 0, 2 × f (1.3, 5.68416) = 2, 95576

y(1, 4) ≈ y2 = y1 + k2 = 4, 584 + 2, 95576 = 7, 53976.

k1 = h f (x2 , y2 ) = 0, 2 × 21, 1113 = 4, 22227

k2 = h f (x2 + h/2, y2 + k1 /2) = 0, 2 × f (1.5, 9.6509) = 5, 79054

y(1, 6) ≈ y3 = y2 + k2 = 7, 53976 + 5, 79054 = 13, 3303.

k1 = h f (x3 , y3 ) = 0, 2 × 42, 657 = 8, 53139

k2 = h f (x3 + h/2, y3 + k1 /2) = 0, 2 × f (1.7, 17.596) = 11, 9653

y(1, 8) ≈ y4 = y3 + k2 = 13, 3303 + 11, 9653 = 25, 2956.

k1 = h f (x4 , y4 ) = 0.2 × 91, 0641 = 18, 2128

k2 = h f (x4 + h/2, y4 + k1 /2) = 0, 2 × f (1.9, 34.402) = 26, 1455

y(2, 0) ≈ y5 = y4 + k2 = 25, 2956 + 26, 1455 = 51, 4411.

A tabela e a figura abaixo resumem os resultados obtidos:


7.2. Método de Runge-Kutta de 2ª ordem 159

xi y(xi ) yi Err. Rel.


1.0 3.0 3.0 0
1.2 4.6581 4.584 0.015912
1.4 7.8351 7.5398 0.037693
1.6 14.276 13.33 0.066274
1.8 28.18 25.296 0.10236
2.0 60.257 51.441 0.1463

Perceba que o método melhora consideravelmente a aproximação em relação ao


método de Euler mesmo utilizando a mesma quantia de pontos.

7.2.1 Implementação

A implementação do método de Runge-Kutta de segunda ordem é essencialmente a


mesma da feita para o método de Euler. De fato, a única alteração necessária é na expressão
dentro do for correspondente a (7.3). O código abaixo mostra esta implementação.

Código 7.2 – Método de Runge-Kutta de 2a ordem.


1 % DESCRICAO : Implementacao do metodo de RK2 .
2 %
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 ] = metRK2 (f , x0 , y0 , xn , n )
13
14 h = ( xn - x0 ) / n ;
15 x = ( x0 : h : xn ) ';
160 Capítulo 7. Equações Diferenciais Ordinárias

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

Note que usamos as variáveis k1 e k2 individualmente pois são apenas valores


auxiliares e conhecê-los não é de nosso interesse para a solução aproximada final (apenas
usamos eles e depois podemos sobrescrever).

7.3 Método de Runge-Kutta de 4ª ordem

Assim como o método de segunda ordem, o método de Runge-Kutta de quarta


ordem faz uso das regras de integração numérica e da série de Taylor para apresentar um
método de alta ordem para aproximar a solução de EDOs sem na necessidade de cálculos
de derivadas.

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

Exemplo 7.3 Problema: Aproximar o exemplo apresentado no método de Euler usando


o método de Runge-Kutta de quarta ordem.

Solução: Para calcular a aproximação pelo método de Runge-Kutta calculamos


7.3. Método de Runge-Kutta de 4ª ordem 161

cada um dos ki e por fim o novo yi+1 :

k1 = h f (x0 , y0 ) = 0, 2 × 6 = 1, 2

k2 = h f (x0 + h/2, y0 + k1 /2) = 0, 2 × f (1.1, 3.6) = 1, 584

k3 = h f (x0 + h/2, y0 + k2 /2) = 0, 2 × f (1.1, 3.792) = 1, 66848

k4 = h f (x0 + h, y0 + k3 ) = 0, 2 × f (1.2, 4.66848) = 2, 24087

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

No caso do RK4 é importante notas que os valores de x utilizados são xi , xi + h/2


(duas vezes) e xi + h que, na verdade, é xi+1 . É importante tomar cuidado para não trocar
este valores. Além disso, na segunda componente de f utilizamos k1 /2, k2 /2 mas apenas
k3 (sem ser dividido por 2).

Para os demais pontos temos:

k1 = h f (x1 , y1 ) = 0, 2 × 11, 1783 = 2, 23567

k2 = h f (x1 + h/2, y1 + k1 /2) = 0, 2 × f (1.3, 5.77547) = 3, 00325

k3 = h f (x1 + h/2, y1 + k2 /2) = 0, 2 × f (1.3, 6.15926) = 3, 20282

k4 = h f (x1 + h, y1 + k3 ) = 0, 2 × f (1.4, 7.86045) = 4, 40185

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

k1 =h f (x2 , y2 ) = 0, 2 × 21, 9312 = 4, 38624

k2 =h f (x2 + h/2, y2 + k1 /2) = 0, 2 × f (1.5, 10.0257) = 6, 01542

k3 =h f (x2 + h/2, y2 + k2 /2) = 0, 2 × f (1.5, 10.8403) = 6, 50417

k4 =h f (x2 + h, y2 + k3 ) = 0, 2 × f (1.6, 14.3368) = 9, 17552

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

k1 = h f (x3 , y3 ) = 0, 2 × 45, 6514 = 9, 13029

k2 = h f (x3 + h/2, y3 + k1 /2) = 0, 2 × f (1.7, 18.8312) = 12, 8052

k3 = h f (x3 + h/2, y3 + k2 /2) = 0, 2 × f (1.7, 20.6687) = 14, 0547

k4 = h f (x3 + h, y3 + k3 ) = 0, 2 × f (1.8, 28.3208) = 20, 391

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

k1 = h f (x4 , y4 ) = 0, 2 × 101, 303 = 20, 2605

k2 = h f (x4 + h/2, y4 + k1 /2) = 0, 2 × f (1.9, 38.2698) = 29, 0851

k3 = h f (x4 + h/2, y4 + k2 /2) = 0, 2 × f (1.9, 42.6821) = 32, 4384

k4 = h f (x4 + h, y4 + k3 ) = 0, 2 × f (2, 60.578) = 48, 4624

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

A tabela e a figura abaixo resumem os resultados obtidos:

xi y(xi ) yi Err. Rel.


1.0 3.0 3.0 0
1.2 4.6581 4.6576 0.00010374
1.4 7.8351 7.8326 0.00032043
1.6 14.276 14.266 0.00072795
1.8 28.18 28.14 0.0014338
2.0 60.257 60.101 0.0025785

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.

Mesmo demandando mais operações em cada passo1 o método RK4 é sempre o


melhor dos três apresentados. De fato, é possível testar o método de Euler com 4 vezes
mais intervalos, igualando assim o número de operações entre Euler e RK4, e veremos que
ainda assim o RK4 obterão uma aproximação muito melhor do que o Euler.

7.3.1 Implementação

Assim como o método de segunda ordem, a implementação do método de Runge-


Kutta de quarta ordem é essencialmente a mesma da feita para o método de Euler.
Novamente, a única alteração necessária é na expressão dentro do for correspondente a
(7.4). O código abaixo mostra esta implementação.

Código 7.3 – Método de Runge-Kutta de 4a ordem.


1 % DESCRICAO : Implementacao do metodo de RK4 .
2 %
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 .
1
Não confundir passo com iteração.
164 Capítulo 7. Equações Diferenciais Ordinárias

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 ] = metRK4 (f , x0 , y0 , xn , n )
13
14 h = ( xn - x0 ) / n ;
15
16 x = ( x0 : h : xn ) ';
17 y = zeros ( n +1 ,1) ;
18 y (1) = y0 ;
19
20 for i = 1: n
21 k1 = h * f ( x ( i ) , y(i) );
22 k2 = h * f ( x ( i ) + h /2 , y ( i ) + k1 /2 ) ;
23 k3 = h * f ( x ( i ) + h /2 , y ( i ) + k2 /2 ) ;
24 k4 = h * f ( x ( i ) + h , y ( i ) + k3 );
25 y ( i +1) = y ( i ) + ( k1 +2* k2 +2* k3 + k4 ) /6;
26 end
7.4. Exercícios 165

7.4 Exercícios

1. Aplique os 3 métodos estudados (Euler, RK2 e RK4) para encontrar as aproximações


das soluções de cada um dos seguintes problemas de valor inicial.
2 − 2ty
a) y 0 = , 0 ≤ t ≤ 1, y(0) = 1 e h = 0.2.
t2 + 1
y2
b) y 0 = , 1 ≤ t ≤ 2, y(1) = −1/ln(2) e h = 0.25.
t+1
y2 + y
c) y 0 = , 1 ≤ t ≤ 3, y(1) = −2 e h = 0.4.
t
4t
d) y 0 = −ty + , 0 ≤ t ≤ 1, y(0) = 1 e h = 0.2.
y
2. As soluções exatas dos problemas da questão anterior estão dadas abaixo. Calcule o
erro absoluto cometido por cada método no ponto final.
2t + 1
a) y(t) = .
t2 + 1
−1
b) y(t) = .
ln(t + 1)
2t
c) y(t) = .
1 − 2t

d) y(t) = 4 − 3e−t2 .

3. Aproxime a solução da EDO:



y 00 + 4y = cos(x), 0 ≤ x ≤ π/4

= 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.

4. Escreva um script para comparar os métodos de Euler e RK4 da seguinte forma:


Fixe um número de intervalos para o RK4 e calcule o erro absoluto no último
ponto. Teste o método de Euler até que o erro obtido com ele seja equivalente (não
necessariamente igual, apenas similar) ao do RK4. Use como problema teste qualquer
um dos problemas apresentados neste capítulo que contenha solução exata.

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

i xi yiEuler yiRK2 yiRK4


0
1
..
.

Além disso, o script deve plotar o gráfico das 3 soluções aproximadas (em uma
mesma figura).

6. Escreve um script para analisar a velocidade de convergência dos três métodos


estudados. Isto é, um script que testa automaticamente cada um dos métodos
para vários valores de h.

Ao final, o código deve exibir uma tabela com a seguinte estrutura:

h n ERREuler T AXAEuler ERRRK2 T AXARK2 ERRRK4 T AXARK4


0.5 0 0 0
0.25
0.125
0.0625
0.03125

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

naquele instante; isto é, a taxa de natalidade (presa) é k1 x1 (t). A taxa de mortalidade


da presa depende tanto do número de presas quanto de predadores naquele instante.
Por simplicidade, consideramos a taxa de mortalidade (presa) igual a k2 x1 (t)x2 (t).
A taxa de natalidade de predadores, por outro lado, depende de seu suprimento de
alimentos, x1 (t), assim como do número de predadores disponíveis para o propósito
da reprodução. Por essa razão, consideramos que a taxa de natalidade (predador) seja
k3 x1 (t)x2 (t). A taxa de mortalidade dos predadores será considerada proporcional ao
número de predadores vivos naquele instante; isto é, a taxa de mortalidade (predador)
é k4 x2 (t).

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

x0 (t) = k3 x1 (t)x2 (t) − k4 x2 (t).




2

Resolva este problema para 0 ≤ t ≤ 4 e h = 0.1, considerando que a população


inicial de presas seja 1000 e de predadores seja 500 e que as constantes sejam k1 = 3,
k2 = 0.002, k3 = 0.0006, k4 = 0.4. Esboce um gráfico das soluções para este problema
(em uma mesma figura) mostrando a evolução das duas populações ao longo do
tempo. Esboce um segundo gráfico com uma curva da relação presa (em x) e predador
(em y). Aplique os 3 métodos estudados (Euler, RK2, RK4).

8. Similar ao problema anterior, podemos estudar o comportamento de duas espécies


competindo pelo mesmo suprimento de alimentos. Se o número de indivíduos de cada
espécie vivo no instante t é denotada por x1 (t) e x2 (t), é frequentemente suposto
que, apesar de a taxa de natalidade de cada uma das espécies ser simplesmente
proporcional ao número de espécies vivas naquele instante, a taxa de mortalidade de
cada espécie depende da população de ambas as espécies.

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

x0 (t) = x2 (t)(2 − 0.0002x1 (t) − 0.0001x2 (t)).




2
168 Capítulo 7. Equações Diferenciais Ordinárias

Se for conhecido que a população inicial de cada espécie é de 10000 indivíduos,


encontre a solução deste sistema para 0 ≤ t ≤ 4 com h = 0.1. Faça gráficos
semelhantes aos da questão anterior. Aplique os 3 métodos estudados (Euler, RK2,
RK4).

9. Considere um sistema (denominado oscilador harmônico amortecido) constituído de


uma massa m presa a uma mola. Usando a Lei de Hooke e a segunda lei de Newton
é possível escrever a equação do movimento deste sistema como:

mx00 (t) + µx0 (t) + kx(t) = 0,

em que

• t é o tempo de observação.

• x(t) é a posição unidimensional da massa em relação a posição de repouso.

• k é a constante da mola.

• µ é uma constante positiva associada ao atrito.

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

8 MATLAB básico para Cálculo Numérico

Este capítulo dedica-se a introduzir o uso do software MATLAB e agrupar os


principais comandos que poderão ser necessários no decorrer do curso.

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.

Para um primeiro contato com os softwares, sugere-se fortemente uma leitura


detalhada do material em paralelo com testes e experimentações com os códigos. Indivi-
dualmente, cada function é intuitiva e facilmente compreendida, porém somente o uso
repetitivo permite a assimilação das técnicas de programação e das ferramentas
disponíveis.

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.

8.1 Sobre o MATLAB

O MATLAB (abreviatura de MATrix LABoratory) é um software criado no fim dos


anos 1970 por Cleve Moler, então presidente do departamento de ciências da computação da
Universidade do Novo México. Ele logo se espalhou para outras universidades e encontrou
um forte uso no âmbito da comunidade de matemática aplicada. Jack Little, um engenheiro,
conheceu a linguagem MATLAB, durante uma visita feita por Moler a Universidade de
Stanford em 1983. Reconhecendo seu potencial comercial, ele juntou-se a Moler e Steve
Bangert, reescreveram MATLAB em C e em 1984 fundaram a MathWorks e prosseguiram
no seu desenvolvimento. Este programa é destinado ao desenvolvimento e implementação
de algoritmos numéricos ou simbólicos que oferece ao usuário um ambiente interativo
de programação para estudo e pesquisa nas diversas áreas das ciências exatas. Devido à
170 Capítulo 8. MATLAB básico para Cálculo Numérico

sua praticidade, essa poderosa ferramenta computacional vem sendo utilizada tanto em
universidades quanto em empresas do mundo todo.

Em relação à linguagem de programação tradicional (como C/C++ ou Fortran), o


desenvolvimento de algoritmos no ambiente MATLAB é sem dúvida mais fácil e rápido.
No meio universitário, o MATLAB tornou-se quase que uma ferramenta padrão em cursos
introdutórios e avançados de Álgebra Aplicada, Processamento de Sinais, Sistemas de
Controle, Estatísticas e inúmeras outras áreas do conhecimento.

O MATLAB contempla ainda uma grande família de aplicações específicas, as


quais são denominadas Toolboxes (caixa de ferramentas). Estes Toolboxes são conjuntos
abrangentes de funções MATLAB cujo objetivo é resolver problemas de áreas específicas,
tais como: Processamento de Sinais, Projeto de Sistema de Controle, Simulação Dinâmica
de Sistemas, Identificação de Sistemas, Redes Neuronais, Lógica Fuzzy (nebulosa ou difusa),
Otimização de Sistemas, Cálculo Simbólico e outras áreas.

A figura 17 apresenta algumas instituições que já utilizam o MATLAB. Além disso,


recentemente a Petrobas também começou a utilizar o MATLAB na sua área de inovação,
exploração e produção.

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

DICA: No Brasil, a Opencadd é a distribuidora do MATLAB. Na página da empresa


<https://opencadd.com.br/> e no canal dela no Youtube <https://www.youtube.com/c/
Opencadd/> você pode encontrar treinamentos em vídeo sobre diversos temas avançados
de engenharia. Apesar de a grande maioria dos temas serem distantes do propósito da
disciplina, é interessante conhecer algumas das possibilidades que o MATLAB te permite.

A MathWorks disponibiliza diversas ferramentas que auxiliam no uso do MATLAB,


inclusive uma versão online do software e espaço de armazenamento em nuvem. Por hora,
a mais importante é File Exchange disponível no link <https://www.mathworks.com/
matlabcentral/fileexchange/> ou através do botão Add-Ons no MATLAB.

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

Desde o ano de 2021 a UTFPR disponibiliza a licença Campus-Wide do MATLAB.


Isso significa que todo discente da instituição tem direito a uma licença do software para
ser instalado no seu computador pessoal.

Para instalar o programa no seu computador siga os passos abaixo:

1. Acesse a página da MathWorks: <https://www.mathworks.com/>

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.

4. Tento concluído o download, execute o instalador. O procedimento de instalação é


bem intuitivo (possivelmente você precisará inserir seu login e senha novamente).
172 Capítulo 8. MATLAB básico para Cálculo Numérico

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):

• Curve Fitting Toolbox

• MATLAB Report Generator

• Statistics and Machine Learning Toolbox

• Symbolic Math Toolbox

IMPORTANTE: Reserve um período de tempo grande (1 a 2 horas) para realizar


a instalação do MATLAB. Esse tempo varia muito dependendo das configurações do
seu computador.

8.2 Aspectos Gerais

O ambiente do MATLAB, no seu layout padrão, é composto por quatro janelas


principais (veja a figura 18):

• Janela de comandos (Command Window): Onde os comandos e funções podem ser


executados. Uma vez executados os comandos não pode ser editados;

• Gerenciador de arquivos (Current Folder): Diretório no qual o MATLAB irá buscar


os códigos do usuário, isto é, o seu Diretório Atual deve ser aquele que contém os
arquivos onde você está trabalhando. Pode ser alterado na barra superior no ícone
“Escolher diretório”.

• Ambiente de trabalho (Workspace): Apresentam as variáveis que estão declaradas.


Pode ser limpado através do comando clear;

• Histórico de comandos (Command History): Histórico das instruções já executadas.


Podem ser acessadas através das teclas do teclado ou com duplo clique.
8.2. Aspectos Gerais 173

Figura 18 – Layout básico do MATLAB.

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):

1. Este botão abre a janela de configurações do programa. Dentre as várias possibilidades,


destacam-se a alteração da fonte e das cores do programa.

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.

9. No canto inferior esquerdo o programa indica o status de execução. Os três estados


básicos são Ready (pronto e aguardando instruções); Waiting for input (aguardando
alguma entrada manual de informação durante uma execução); Busy (executando
instruções).

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.

Os arquivos do MATLAB (tanto function quanto script) tem formato “.m”.

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

Figura 19 – Recursos adicionais do MATLAB.

IMPORTANTE: Ao programar no MATLAB usamos duas janelas. No Editor criamos


arquivos que podem ser salvos e levados de um computador para outro como qualquer
arquivo comum de texto. Já a Janela de comandos é utilizada para executar os códigos
escritos no Editor, visualizar respostas exibidas pelo código e eventuais contas elementares
que não nos interesse guardar.

8.2.1 Comandos Iniciais

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.

Ainda na janela de comandos podemos realizar as operações básicas semelhante a


qualquer calculadora científica:

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 .

IMPORTANTE: Oo símbolo “=” no MATLAB denota atribuição. Ou seja, escrever


a = 1 significa que você está instruindo o computador a atribuir o valor 1 à variável a.

Os próximos comandos visam tornar o processo de implementação e teste mais ágil


e permite acessar a documentação do software para aprender e relembrar o funcionamento
de functions disponíveis.

• clc: Limpa a janela de comandos, porém, não apaga as variáveis declaradas. Teste
este comando e veja o efeito;

• clear: Limpa as variáveis declaradas (listadas no Ambiente de trabalho), mas preserva


a informação apresentada na janela de comandos;

• help: Acessa a documentação do MATLAB fornecendo explicações sobre as functions


implementadas e seu funcionamento. Exemplo: help roots;

• lookfor: Busca na documentação do MATLAB qualquer function que contenha um


dado termo. Exemplo: lookfor inverse. Cuidado, este comando pode tomar algum
tempo para ser executado.
2
se você está familiarizado com outras linguagens de programação notará que os passos i) declarar
variável; ii) alocar memória; iii) e atribuir valor; foram realizado de forma conjunta. Isso vem da
proposta do MATLAB de facilitar a programação.
8.2. Aspectos Gerais 177

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.

8.2.2 Nome de Variáveis

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.

• O MATLAB faz diferenciação entre letras maiúsculas e minúsculas, isto é,


as variáveis media e meDia são consideradas diferentes.

• 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.

AVISO: Apesar de possuírem nomenclaturas associadas, as variáveis x1 e x2 não


tem relação nenhuma podendo uma ser uma matriz e outra ser um número. Além
disso, não devemos confundir x1 com a primeira componente da variável x.
178 Capítulo 8. MATLAB básico para Cálculo Numérico

• 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.

• O único caractere especial permitido em nomes de variáveis é o underline


“_”, e que não pode ser o caractere inicial. Os demais como %, $, @, acentuações e
pontuações não são permitidos.

• Não é permitido espaços no nome das variáveis.

8.2.3 Variáveis predefinidas

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

• i e j: ambas denotam a unidade imaginária nos números complexos. Como estamos


assumindo ao longo do texto que tudo que fazemos está nos números reais, podemos
utilizar i e j para indexar laços e fazer referência a elementos de matrizes e vetores
(como é usual na álgebra linear).

• pi: valor do π = 4 atan(1) ≈ 3.14159265358979 com alta precisão.

• Inf : infinito (exemplo: 1 ÷ 0). A menos que seja esperado, geralmente indica um
erro de implementação do código.

• NaN: do inglês not-a-number (exemplo: 0 ÷ 0). Também costuma indicar um erro


de implementação do código.
8.2. Aspectos Gerais 179

8.2.4 Formatos de exibição

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:

1 >> 10^( -3)


2 ans =
3 1.0000 e -03

Ou seja, primeiras casas decimais, seguido pela letra e, o sinal da potência e por último a
potência.

IMPORTANTE: Não confunda o e que aparece na notação científica com a constante


e ≈ 2.718281828459046.

IMPORTANTE: Da expressão acima também é possível perceber que o MATLAB


utiliza ponto para indicar as casas decimais.

O MATLAB aceita diversos formatos de exibição. Estes formatos nada tem a


ver com a precisão dos resultados, mas sim com a forma com a qual eles são exibidos
na janela de comandos. A precisão dos resultados está ligada com os fatores discutidos
no capítulo 1. A tabela 6 resume os principais formatos aceitos, outros formatos menos
frequentes podem ser encontrados na documentação do format.

Tabela 6 – Lista de formatos básicos de exibição.


Sintaxe Formato Exemplo (pi)
format short precisão simples 3.1416
format long precisão dupla 3.14159265358979
format shorte precisão simples E 3.1416e + 000
format longe precisão dupla E 3.141592653589793e + 000
format shortg melhor entre short e shorte 3.1416
format longg melhor entre long e longe E 3.141592653589793
format rat quociente 355/113

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.

8.3 Matrizes e Vetores


O código abaixo declara a matriz:
 
1 2 3
 
A= 4 5 6
 
 
7 8 9
 
8.3. Matrizes e Vetores 181

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:

• As componentes são definidas por linhas;

• ’[’ indica início da definição da matriz;

• ’]’ indica final da definição da matriz;

• ’ ’ ou ’,’ separa elementos da mesma linha;

• ’;’ encerra definição de linha.

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.

Tendo declarado matrizes e vetores, podemos realizar diversas operações aritméticas


com as variáveis. Além das operações elementares conhecidas da álgebra linear, o MATLAB
também entendem algumas outras operações listadas na tabela 7. Estas operações visam
facilitar, simplificar e acelerar tanto a implementação de um código quanto a sua execução.

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.

O código abaixo mostra o funcionamento de algumas das operações da tabela 7.


182 Capítulo 8. MATLAB básico para Cálculo Numérico

Tabela 7 – Operações básicas para matrizes e vetores.


Operador Descrição
+ Soma
- Subtração
* Multiplicação matricial
.* Multiplicação escalar
./ Divisão escalar
\ Divisão esquerda
∧ Potência matricial
.∧ Potência escalar
’ Transposta
() Precedência

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

IMPORTANTE: As operações .* , ./ e .^ permitem que diversas contas sejam


efetuadas de forma simples e eficiente evitando a necessidade de estruturas de repetição.
Saiba diferenciar estas operações das correspondentes sem o ponto.

8.3.1 Solução de Sistemas Lineares

A operação de divisão esquerda não é padrão do curso de álgebra linear. Na prática,


dada uma matriz B não-singular (isto é, com determinante não nulo) e um vetor v com
dimensões adequadas como os definidos acima, a divisão esquerda B\v encontra o
vetor w para o qual Bw = v. Ou seja, calcula a solução do sistema linear dado3 . O
código abaixo mostra a utilização desta operação.

Código 8.1 – Exemplo de como resolver um sistema linear.


1 >> B = [1 2 3 ; 4 5 6 ; 7 8 10];
2 >> det ( B ) % Function que calcula o determinante de uma matriz
quadrada .
3 ans =
4 -3
5 >> v = [2 5 9] ' % Transpomos uma linha para torna - la coluna .
6 >> w = B \ v % Efetuando a divisao esquerda .
7 w =
8 1
9 -1
10 1
11 >> B * w % Conferindo que w eh a solucao do sistema linear .
12 ans =
3
Pode parecer uma operação até simples, mas por trás da divisão esquerda estão escondidos diversos
métodos numéricos de álgebra linear computacional desenvolvido ao longo dos anos e implementados
com as técnicas mais avançadas conhecidas. Além disso, um grande conjunto de resultados teóricos
auxilia na heurística para decidir qual destes métodos é o mais adequado para o sistema.
184 Capítulo 8. MATLAB básico para Cálculo Numérico

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).

DICA: As relações de precedência são naturais quando fazemos contas manualmente.


Porém, são tão naturais que muitas vezes a sua importância para facilitar as contas passa
desapercebido. Por exemplo, se A, B e C são matrizes de tamanhos compatíveis, então as
operações A ∗ (B + C) e (A ∗ B + A ∗ C) devem resultar na mesma matriz. No entanto, a
segunda forma é muito mais custosa computacional e tomará muito mais tempo que a
primeira. Isso ocorre porque na segunda realizamos dois produtos matriz-matriz e uma
soma de matrizes. Já na primeira temos uma soma de matrizes e apenas um produto de
matrizes.

8.3.2 Indexação

Além de operar com matrizes e vetores é muito importante sabermos manipular


os dados contidos nestes tipos de variáveis. Em problemas práticos, uma matriz ou vetor
guardam informações que tem algum significado.

Por exemplo, se dois vetores t e v contém dados de tempo e velocidade de um carro,


então ao longo de alguma análise podemos nos perguntar “quais foram as velocidades
medidas em um determinado intervalo de tempo?”. Para exibir ou obter essa informação
precisamos buscar no vetor t quais são os índices correspondentes ao intervalo de tempo
de interesse. Tendo estes índices, pegamos as informações de v nos mesmos índices.

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

DICA: Esta uma das principais seções desta apostila.

Í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

Ou seja, o elemento da matriz A na linha 2 e coluna 3 é igual a 6.

Para vetores, utilizamos apenas um índice. Por exemplo:

1 >> v = [10 20 30] '


2 v =
3 10
4 20
5 30
6 >> v (3)
7 ans =
8 30

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

Diferente de muitas linguagens de programação, no MATLAB podemos alterar as


dimensões de uma variável atribuindo um valor à componentes fora das dimensões atuais.
O programa automaticamente irá redimensionar a variável. Por exemplo:

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

Ou seja, usamos a forma geral:

1 <Variável> = <Início>:<Passo>:<Fim>

Um caso particular, que é muito utilizado para índices de matrizes e vetores é


quando o passo é 1. Neste caso, o MATLAB permite que o passo seja omitido. Assim,
podemos usar:

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.

Por exemplo, se A é a matriz


 
1 2 3
 
A= 4 5 6
 
 
7 8 9
 

então obtemos as informações da segunda coluna da seguinte forma:

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

Isso acontece porque o trecho 1:3 fornece o vetor [1 2 3] e, portanto, o que


estamos dizendo ao programa é: “Mostre os elementos de A que estão nas linhas 1, 2 e 3
da coluna 2”.

Em particular, quando queremos selecionar uma coluna ou linha inteira da


matriz podemos omitir o início e final restando apenas os dois pontos:

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

1 >> A (2:3 ,1:2)


2 ans =
3 4 5
4 7 8

Submatrizes com “[” e “]”

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

Note que a ordem na qual os índices aparecem influencia a resposta obtida:

1 >> A ([3 1] ,:)


2 ans =
3 7 8 9
4 1 2 3

Sendo assim, podemos trocar duas linhas de uma matriz usando estes comando:

1 >> A ([1 3] ,:) = A ([3 1] ,:)


2 A =
3 7 8 9
4 4 5 6
5 1 2 3
190 Capítulo 8. MATLAB básico para Cálculo Numérico

Concatenação

Concatenação é o processo de agrupar informações de duas ou mais variáveis


em uma. Para fazer isso utilizamos os colchetes da mesma forma como se estivéssemos
declarando uma matriz. Por exemplo, considere as variáveis abaixo.

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

Podemos agrupar estas variáveis para criar a matriz:


 
1 2 3 10 
 
4 5 6 20 

G=

 
7 8 9 30 
 
 
 
10 20 30 100

uma vez que percebemos que ela tem a estrutura:


 
 
 
 A v 
G=
 
 .
 
 
 
 
vT c

O comando para fazer esta construção é:

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.

Para acessar o Editor podemos:

• digitar edit na Janela de comandos;

• clicar o botão “New Script” no canto esquerdo superior;

• ou pelo atalho “Ctrl+N”.

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

Figura 20 – Editor do MATLAB.

2. Ferramentas para inserir comentários nos códigos (Ctrl+R), remover comentários


(Ctrl+T) e indentar (Ctrl+I). Isso é explicado mais adiante.

3. Gerenciamento de Breakpoints. Essa ferramenta será apresentada à você dependendo


da necessidade que surgir.

4. Botão para salvar e executar o código aberto (F5).

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.

IMPORTANTE: Via de regra o MATLAB funciona da seguinte forma: códigos são


escritos no editor e sua execução ocorre na Janela de comandos.

No Editor é possível criar dois tipos de arquivos básicos (ambos com formato *.m):

• script: Sequência de instruções (código) que serão executadas da primeira até a


última linha caso não encontre nenhum erro. Pode conter chamada de outros scripts
8.4. Editor 193

e functions, carregamento de dados a partir de arquivos, geração de gráficos, etc.


Faz uso do workspace geral.

• function: Caracteriza-se por conter a palavra function na primeira linha. Mais


importante que isso, os arquivos deste tipo são criados para executar tarefas específicas
dentro de um código maior. Tem workspace próprio, isto é, as variáveis que existem
ao longo da execução de uma function são aquelas criadas dentro do
arquivo ou que foram fornecidas como variável de entrada.

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.

IMPORTANTE: Salvo raras exceções, nunca execute diretamente uma function


(botão Run ou F5). Sempre executamos um script. Isso ocorre porque uma function
requer variáveis de entrada e saída.

Como já foi mencionado, o Editor do MATLAB possuem diversas ferramentas para


auxiliar na criação de códigos. Algumas:

• Caracteres especiais como function, for e if aparecem desta forma.

• Códigos dentro de estruturas de seleção e repetição são automaticamente deslocados


para a direita para torná-los mais legíveis. Isso chama-se indentação.

• Comentários irão automaticamente ficar na cor verde: % Isso é um comentário.

• Textos irão automaticamente ficar na cor magenta: 'texto', ou vermelha ’texto


caso esteja faltando uma aspa.

• Parênteses e colchetes tem sua contraparte destacada ao passar o cursor por cima.

• Na barra direita indica onde há erros ou possíveis melhorias do código.

• O sinal de atribuição “=” fica destacado caso não haja ponto e vírgula no final.

• Variáveis que possam conter problemas ficam destacadas.

• A tecla F5 salva e executa o script que está visível.


194 Capítulo 8. MATLAB básico para Cálculo Numérico

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.

IMPORTANTE: Existem algumas limitações em relação ao nome dos arquivos de


scripts. 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
(acentuações, por exemplo) e sem espaço.

8.4.1 Functions

As functions podem ser pensadas como formas generalizadas da noção de função


matemática conhecida. Em resumo, uma function tem um conjuntos de variáveis
de entrada e um conjunto de variáveis de saída, ambos listados na primeira
linha do arquivo. A sintaxe usada para definir uma function segue o padrão:

[Saida1,. . . ,SaidaN] = nome_funcao(Entrada1,. . . ,EntradaM)

Em outras palavras, a function nome_funcao, quando for chamada, receberá as


variáveis de entrada Entrada1,. . . ,EntradaM, fará as instruções dadas ao longo do código
e retornará as informações contidas nas variáveis4 Saida1,. . . ,SaidaN. Por exemplo, a
function det, usada no código 8.1, recebe uma única variável de entrada (matriz do
sistema) e retorna uma única variável de saída (determinante da matriz).

Na próxima seção listamos várias functions pré-disponíveis pelo MATLAB e que


podem ser usadas para evitar códigos extensos e desnecessários.

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.

1 function [ soma , difer ] = operacoes (a , b )


2
3 soma = a + b ;
4 difer = a - b ;

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:

1 >> [s , d ] = operacoes (3 ,5)


2 s =
3 8
4 d =
5 -2

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

IMPORTANTE: Um ponto que pode causar confusão é em relação a passagem de


informações contidas nas variáveis. Na function do exemplo acima as variáveis de saída
eram soma e difer, no entanto ao utilizar a function usamos s e d como variáveis de saída.
Você perceberá que no workspace só estarão listados estas duas últimas. O processo que
ocorre pode ser resumido nos seguintes passos (veja a figura 21):

1. A function é chamada passando as informações das variáveis x e y (3 e 5 neste


caso) para serem atribuídos as variáveis a e b, respectivamente. Nesse ponto, o
workspace do MATLAB contém apenas x e y.

2. Ao acessar a function, o workspace dela é criado. Em seguida, as variáveis a e b são


criadas e recebem as informações passadas.

3. Enquanto o workspace do MATLAB continua contendo apenas x e y, o workspace


da function contém a e b.

4. Passando as linhas 3 e 4, as operações são realizadas e as atribuições são feitas. Com


isso, mais duas variáveis são criadas (soma e difer) e alocadas apenas no workspace
da function.

5. Como o código chegou ao fim, a function retornará as variáveis de saída definidas.

6. As informações contidas nas variáveis soma e difer serão atribuídas as variáveis s e


d, respectivamente.

7. O workspace da function é então apagado junto com as 4 variáveis que lá existiam.

8. Ao final você verá as duas variáveis criadas no workspace do MATLAB.

O entendimento desse processo é importante para compreender a lógica por trás


do gerenciamento das informações que o MATLAB. Alguns erros comuns:

• Tentar acessar/usar uma variável dentro de uma function que está alocada fora do
workspace dela.

• Tentar acessar/usar uma variável do workspace de uma function fora dela.

• Tentar sobrescrever uma variável de um workspace estando em outro.


8.4. Editor 197

Figura 21 – Fluxograma da execução de uma function.

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.

1 % DESCRICAO : Calcula o determinante de uma matriz 2 x2 .


2 %
3 % ENTRDA :
4 % - A : matriz 2 x2 .
5 % SAIDA :
6 % - d : determinante de A .
7 function d = det2x2 ( A )
8
9 d = A (1 ,1) * A (2 ,2) - A (1 ,2) * A (2 ,1) ;

Na próxima seção você verá como testar esta function.


198 Capítulo 8. MATLAB básico para Cálculo Numérico

IMPORTANTE: Podemos perceber no exemplo acima uma duplicidade na sintaxe do


MATLAB. O comando A(1,2) poderia significar:

• Uma function cujo nome é A e está sendo avaliada em 1 (primeiro valor de entrada)
e 2 (segundo valor de entrada).

• A componente da linha 1 e coluna 2 de uma matriz alocada com nome A.

Por isso, é importante sabermos o tipo de informação estará contida em cada


variável (se é uma matriz, uma função algébrica, um vetor, ...).

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).

IMPORTANTE: Existem diversas formas de organizar a implementação de um código


no MATLAB. Nesta apostila utilizaremos a forma esboçada na figura 22 e você deve
obrigatoriamente segui-la também.

Temos a seguinte estrutura: cada método ou semelhante é implementado em uma


function própria. Um único script é implementado e tem o papel de gerenciar todo o teste
ou resolução feita.

A estrutura apresentada na figura 22 segue o conceito de modularização. Isto é,


criar uma function para fazer cada tarefa isoladamente. É por causa disso que iremos
implementar os métodos da forma mais genérica possível, deixando quaisquer
informações sobre o problema que será resolvido para o script. Este formato
8.4. Editor 199

Figura 22 – Estrutura geral das implementações feitas na apostila.

tem diversas vantagens:

• Acelera a implementação e execução de múltiplos problemas.

• Facilita a detecção de erros.

• Facilita a testagem dos módulos.

• Facilita a reutilização dos módulos.

• Facilita a mudança de parâmetros para diversos métodos.

• Evita conflito de variáveis.

• O MATLAB faz uso desse formato para acelerar a execução5 .

Exemplo 8.3 Ao invés de executar a function do exemplo 8.1 na Janela de comandos,


podemos criar um script para testá-lo com diferentes valores. A figura 23 esboça uma forma
simples de usar a function operacoes em um script.

Ainda em relação ao exemplo 8.1, podemos repetir a utilização da function mais de


umavez, em diferentes parte do script e com diferentes parâmetros de entrada. A figura 24
esboça uma possibilidade de fazer isso.

Neste caso, é interessante notar que na linha 3 as variáveis s e t são criadas e


recebem valores 8 e −2, porém ao final da execução eles tem o valor 6 e −10 porque ambas
as variáveis foram alteradas na linha 6. Dessa forma, os valores anteriores foram perdidos.
5
De fato, existe um ganho imenso de desempenho em relação a uma implementação “linear” em apenas
um script.
200 Capítulo 8. MATLAB básico para Cálculo Numérico

Figura 23 – Teste do script para a function operacoes.

Figura 24 – Teste do script com múltiplos usos da function operacoes.

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

Figura 25 – Teste do script para a function det2x2.

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.

IMPORTANTE: Você não deve, em hipótese algum, apresentar códigos usando


a function input.

8.4.3 Dois exemplos simples

Exemplo 8.5 Problema: Criar uma function que recebe um vetor e troca dois elementos
de posição.

Solução 1: Vamos chamar de pos1 e pos2 os índices das componentes do vetor


v que serão trocadas. Para efetuar esta troca de posição não é possível apenas escrever:
202 Capítulo 8. MATLAB básico para Cálculo Numérico

1 v ( pos1 ) = v ( pos2 ) ;
2 v ( pos2 ) = v ( pos1 ) ;

pois na primeira linha estamos perdendo a informação contida em v(pos1) e que é


necessária para a segunda linha. Para contornar isso, primeiro armazenamos a informação
em v(pos1) em uma variável auxiliar, que vamos chamar de aux. O código final pode ser
feito como está abaixo:

Código 8.2 – Function para trocar elementos de um vetor de posição - versão 1.


1 % DESCRICAO : Troca duas componentes de um vetor de posicao .
2 %
3 % ENTRDA :
4 % - v : vetor que serah alterado .
5 % - pos1 : indice de uma linha .
6 % - pos2 : indice de outra linha .
7 % SAIDA :
8 % - v : vetor alterado .
9 function v = troca1 (v , pos1 , pos2 )
10
11 aux = v ( pos1 ) ;
12 v ( pos1 ) = v ( pos2 ) ;
13 v ( pos2 ) = aux ;

Solução 2: A solução 1 é a forma “tradicional” de fazer a troca de linhas. O


MATLAB possui uma segunda forma que permite fazer essa troca de forma mais simples.
De modo geral, acaba-se por não ser necessário uma function para fazer esta operação,
mas aqui ainda iremos apresentar neste formato.

Código 8.3 – Function para trocar elementos de um vetor de posição - versão 2.


1 % DESCRICAO : Troca duas componentes de um vetor de posicao .
2 %
3 % ENTRDA :
4 % - v : vetor que serah alterado .
5 % - pos1 : indice de uma linha .
8.4. Editor 203

6 % - pos2 : indice de outra linha .


7 % SAIDA :
8 % - v : vetor alterado .
9 function v = troca2 (v , pos1 , pos2 )
10
11 v ([ pos1 pos2 ]) = v ([ pos2 pos1 ]) ;

A interpretação da linha 11 deste código é a seguinte: as linhas pos1 e pos2 do


vetor v irão receber (nesta ordem) as linhas pos2 e pos1.

O script abaixo mostra o funcionamento do código.

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.

Solução: Sabemos, da álgebra linear, que a norma de um vetor x é dado por


v
u n
kxk = = (xT x)1/2 .
uX
t x2 i
i=1

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

Código 8.4 – Exemplo de function para calcular norma de vetor.

1 % DESCRICAO : Calcula a norma de um vetor .


2 %
3 % ENTRDA :
4 % - x : vetor .
5 % SAIDA :
6 % - y : norma do vetor .
7 function y = norma_v1 ( x )
8
9 y = (x '* x ) ^(1/2) ;

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.

1 % Script para testar a


function norma_v1 . m 1 >> exemploNorma
2 2 y =
3 x = [0 0.1 0.2 0.3] '; % vetor . 3 0.374165738677394
4 y = norma_v1 ( x ) 4 y2 =
5 5 0.374165738677394
6 y2 = norm ( x )

A function norm usada no script acima pertence a biblioteca básica do MATLAB e


calcula a mesma norma proposta no exercício. Na prática, usamos as functions prontas
pois tornam o código mais enxuto e estável, além de economizar tempo implementando e
testando um código.

8.5 Funções Básicas

O MATLAB possui um grande número de functions pré-implementadas que realizam


as mais diversas tarefas. Nesta seção listamos e descrevemos as principais functions
necessárias para os códigos desta apostila.
8.5. Funções Básicas 205

abs

Calcula o valor absoluto (módulo) do número, vetor ou matriz dado.

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

Calcula o determinante de uma matriz quadrada dada.

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

Retorna uma matriz identidade de uma dimensão dada.

1 >> A = eye (3)


2 A =
3 1 0 0
4 0 1 0
5 0 0 1

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

Retorna o número de elementos em um vetor.

1 >> v = rand (5 ,1) ;


2 >> n = length ( v )
3 n =
4 5

max

Caso a variável de entrada seja um vetor, retorna o valor da maior das componentes.

1 >> v = rand (4 ,1)


2 v =
3 0.8407
4 0.2543
5 0.8143
6 0.2435
7 >> maximo = max ( v )
8 maximo =
9 0.8407

Caso a variável de entrada seja uma matriz, retorna um vetor com o máximo de cada
coluna.

1 >> A = rand (3 ,4)


2 A =
3 0.5853 0.2551 0.8909 0.1386
208 Capítulo 8. MATLAB básico para Cálculo Numérico

4 0.2238 0.5060 0.9593 0.1493


5 0.7513 0.6991 0.5472 0.2575
6 >> maximo = max ( A )
7 maximo =
8 0.7513 0.6991 0.9593 0.2575

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

Análoga a function max, calcula o menor valor entre as componentes de uma


variável.

1 >> A = rand (3 ,4)


2 A =
3 0.5853 0.2551 0.8909 0.1386
4 0.2238 0.5060 0.9593 0.1493
5 0.7513 0.6991 0.5472 0.2575
6 >> minimo = min ( A )
7 minimo =
8 0.2238 0.2551 0.5472 0.1386

ones

Cria uma matriz de dimensão dada com todas as componentes iguais a um.

1 >> A = ones (3)


2 A =
3 1 1 1
4 1 1 1
5 1 1 1
6 >> B = ones (2 ,3)
7 B =
8.5. Funções Básicas 209

8 1 1 1
9 1 1 1

prod

Semelhante a function sum, calcula o produtório das componente de um vetor (ou


matriz), isto é, o produto entre as componentes do vetor.

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.

1 >> A = rand (3 ,4)


2 A =
3 0.0975 0.9575 0.9706 0.8003
4 0.2785 0.9649 0.9572 0.1419
5 0.5469 0.1576 0.4854 0.4218

DICA: A function rand é ideal para testar códigos envolvendo matrizes pois permite
criá-las de qualquer dimensão desejada facilmente.

size

Retorna as dimensões de uma variável (matriz usualmente). Pode retornar um


vetor com as dimensões ou cada dimensão em uma variável separada.

1 >> A = rand (3 ,4) ;


2 >> dim = size ( A )
3 dim =
210 Capítulo 8. MATLAB básico para Cálculo Numérico

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).

1 >> A = rand (3 ,4) ;


2 >> m = size (A ,1)
3 m =
4 3
5 >> n = size (A ,2)
6 n =
7 4

sum

Caso a variável de entrada seja um vetor, retorna a soma de todas as componentes.


Caso a variável de entrada seja uma matriz, retorna a soma das componentes de cada
coluna.

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.

1 >> A = zeros (3)


2 A =
3 0 0 0
4 0 0 0
5 0 0 0
6 >> B = zeros (3 ,2)
7 B =
8 0 0
9 0 0
10 0 0

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:

1 >> license ( ' test ' , ' Symbolic_Toolbox ')


2 ans =
3 1

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.

Tendo a toolbox instalada, podemos começar a manipular um novo tipo de variável,


conhecida como variável simbólica. Este tipo de variável permite manipularmos algebrica-
mente variáveis, escrever e resolver equações, declarar funções, derivar e integrar. O código
abaixo mostra algumas funções possíveis.

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

Por fim, as functions solve e dsolve resolvem equações algébricas e diferenciais,


respectivamente.

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

8.5.2 Funções de arrendondamento

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.

Tabela 8 – Funções de arrendondamento.


Function Descrição
mod Resto da divisão entre dois números
fix Retorna apenas a parte inteira do número
round Arredonda para o número inteiro mais próximo
ceil Arredonda para cima
floor Arredonda para baixo
214 Capítulo 8. MATLAB básico para Cálculo Numérico

8.5.3 Funções anônimas

Como mencionado, nos códigos apresentados nesta apostila utilizamos a estrutura


dada na figura 22. Para isso, frequentemente é necessários que funções algébricas sejam
passadas como parâmetro para um método.

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.

A segunda possibilidade é utilizar a function inline. Apesar de ser mais prática


que a anterior, esta é uma forma obsoleta6 e lenta na execução. Por isso, também não
iremos utilizá-la.

A forma mais recomendada de manusear funções algébricas é um tipo


de variável chamada função anônima. Sua estrutura geral é dada por:

1 fun = @( arg1 , arg2 ,. . . ) ( expression ) ;

Exemplo 8.7 No caso da função

f (x, y) = sen(x) + ey

temos dois argumentos (variáveis independente), portanto fazemos:

1 >> f = @( x , y ) ( sin ( x ) + exp ( y ) )


2 f =
3 function_handle with value :
4 @( x , y ) ( sin ( x ) + exp ( y ) )

e utilizamos da mesma forma como uma função algébrica:


6
Na documentação do MATLAB você encontrará a frase: “inline will be removed in a future release.
Use anonymous functions instead”
8.5. Funções Básicas 215

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.

8.5.4 Funções Matemáticas

Todas as funções matemáticas estão pré-implementadas no MATLAB e devem


ser priorizadas em relação a outras opções (implementações próprias). Quase todas estão
implementadas na versão matricial, isto é, se aplicarmos a função seno em uma matriz (ou
vetor), obteremos uma matriz com o seno de cada componente da variável dada. Com isso,
evitamos a necessidade de laços de repetição tediosos e ineficientes.

A tabela 9 abaixo lista as principais funções trigonométricas. Todas recebem e


retornam uma variável. As funções usam ângulos em radianos.

Tabela 9 – Funções trigonométricas.


Function Descrição Function Descrição
sin seno asin Função inversa do seno (arcoseno)
cos cosseno acos Função inversa do cosseno
tan Tangente atan Função inversa do tangente
sec Secante asec Função inversa do secante
csc Cossecante acsc Função inversa do cossecante
cot Cotangente acot Função inversa do cotangente

DICA: Além das funções trigonométricas da tabela 9, o MATLAB possui versões em


graus (que evita conversões), funções hiperbólicas e até mesmo funções do tipo sinpi que
calcula sen(πx) de forma mais estável. Você pode consultar sobre elas na documentação.

sqrt

Da denominação em inglês (square root), a function sqrt calcula a raiz quadrada


de um número (ou vários se a variável de entrada for uma matriz).

1 >> sqrt ([1 2 3] ')


216 Capítulo 8. MATLAB básico para Cálculo Numérico

2 ans =
3 1.0000
4 1.4142
5 1.7321

Caso o número fornecido seja negativo, calculará utilizando raízes complexas.

exp

Calcula a exponencial de uma matriz, vetor ou número dado.

1 >> y = exp ([1 2 3] ')


2 y =
3 2.7183
4 7.3891
5 20.0855

log e log10

Calculam o logaritmo de um valor dado (ou das componentes de uma matriz). A


function log calcula o logaritmo natural, ou seja, o ln. Já log10 calcula o logaritmo na
base 10.

1 >> y = log ([ exp (1) 10] ')


2 y =
3 1.0000
4 2.3026
5 >> y = log10 ([ exp (1) 10] ')
6 y =
7 0.4343
8 1.0000
8.6. Variáveis de texto 217

8.6 Variáveis de texto


Variável de texto, do inglês string ou char, é um tipo de variável disponível no
MATLAB de grande versatilidade. A principal utilidade (ao menos nesta apostila) deste
tipo de dado é exibir informações e apresentar resultados enquanto um código é executado.

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.

Figura 26 – Declaração de variáveis de texto.

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

e também podemos manipulá-las:

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.

Voltando a figura 26, a variável b é uma string e é tratada como um elemento


único, um conjunto, por isso tem tamanho 1 × 1. Este tipo de variáveis é relativamente
recente ao MATLAB.

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:

1 >> A = rand (3)


2 A =
3 0.0975 0.9575 0.9706
4 0.2785 0.9649 0.9572
5 0.5469 0.1576 0.4854
6 >> disp ( A )
7 0.0975 0.9575 0.9706
8 0.2785 0.9649 0.9572
9 0.5469 0.1576 0.4854
8.6. Variáveis de texto 219

DICA: Note como a parte “A = ”, muitas vezes irrelevante para quem está executando o
código, é omitida ao usarmos disp.

Se desejamos mostrar um texto, podemos utilizar:

1 >> disp ( 'O resultado encontrado foi : ') ; disp (4)


2 O resultado encontrado foi :
3 4

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:

1 disp ([ 'O resultado encontrado foi : ' num2str (4) ])

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.

Figura 27 – Utilização das aspas duplas no disp.

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

Código 8.5 – Exemplo script para testar func-


tion.
1 % Script para testar a
function norma_v1 . m
2 1 A norma do vetor eh :

3 x = [0 0.1 0.2 0.3] '; % vetor . 2 0.3742

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.

1 fprintf ( ' %0.5 g \ n ' ,(1+ sqrt (5) ) /2) % 1.618


2 fprintf ( ' %0.5 g \ n ' ,1/ eps ) % 4.5036 e +15
3 fprintf ( ' %15.5 f \ n ' ,1/ eps ) % 4503599627370496.00000
4 fprintf ( '% d \ n ' , round ( pi ) ) % 3
5 fprintf ( '% s \ n ' , ' hello ') % hello
6 fprintf ( ' The array is % dx % d .\ n ' ,2 ,3) % The array is 2 x3 .

DICA: Os comandos acima também funcionam com as aspas duplas.

Em resumo, o primeiro parâmetro de entrada é um texto com a frase e os marcadores


desejados. Em seguida, listamos as informações que serão colocadas nos marcadores.

1 >> fprintf ( ' Para texto : % s \ nPara numeros inteiros : % d \ nPara


numeros nao - inteiros : %5.2 f \ n ' , ' abc ' ,15 ,1/3)
2 Para texto : abc
3 Para numeros inteiros : 15
4 Para numeros nao - inteiros : 0.33
8.7. Estruturas de seleção e repetição 221

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.

8.7 Estruturas de seleção e repetição

A parte mais complicada na programação costuma ser a construção de um algoritmo


eficiente para resolver o problema que desejamos. Como você pode ver nos códigos ao longo
desta apostila, os métodos implementados usualmente requerem que façamos repetições
(iterações, por exemplo) e consideremos casos dependendo de informações do problema e
do método.

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.

8.7.1 Lógica Booleana

Os operadores lógicos de comparação entre duas entidades (variáveis ou valores)


são listados na tabela 10.

Tabela 10 – Lista de operadores lógicos básicos.


Símbolo Teste
== Igual
∼= Diferente
< Menor que
> Maior que
<= Menor ou igual
>= Maior ou igual
222 Capítulo 8. MATLAB básico para Cálculo Numérico

Os operadores de desigualdade são idênticos aos usuais. Já os operadores de


igualdade (==) e não-igualdade (∼=) não tem uma notação tão comum aos leigos, mas
seguem o raciocínio simples. Para testar a igualdade entre dois objetos usamos == e para
testar se dois objetos são diferentes usamos ∼=.

Deixaremos para dar exemplos mais interessantes junto as estruturas.

IMPORTANTE: Um teste lógico retornará uma resposta binária: 0 se a expressão for


falsa e 1 se ela for verdadeira.

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?”:

1 >> ~(10 < 9)


8.7. Estruturas de seleção e repetição 223

Tabela 11 – Lista de operadores lógicos de combinação.


Símbolo Operador
∼ Negação
& E
| OU

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.

O símbolo de E lógico pergunta se duas sentenças são válidas ao mesmo tempo.


Por exemplo, a sentença abaixo é lida como “10 é maior que 9 E 11 é menor que 10?”:

1 >> 10 > 9 & 11 < 10


2 ans =
3 logical
4 0

É 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:

1 >> 10 > 9 | 11 < 10


2 ans =
3 logical
4 1
224 Capítulo 8. MATLAB básico para Cálculo Numérico

pois a primeira parte da sentença é verdadeira, o que torna a sentença inteira verdadeira.

As tabelas abaixo resumem a iteração E e OU entre duas sentenças. Usamos V


para verdadeiro e F para falso.

Tabela 12 – Resumo dos casos para E e OU.


E V F OU V F
V V F V V V
F F F F V F

Todos os operadores lógicos podem ser usados na forma vetorial, isto é, para
comparar várias instâncias simultaneamente. Por exemplo:

1 >> a = rand (1 ,4)


2 a =
3 0.4323 0.9390 0.8678 0.6137
4 >> a > 0.7
5 ans =
6 1 x4 logical array
7 0 1 1 0

Podemos combinar a forma acima com a indexação da variável para fazer atribuições
ou manipulações:

1 >> b = rand (1 ,4)


2 b =
3 0.9580 0.8383 0.9379 0.2933
4 >> b ( a > 0.7) = 1
5 b =
6 0.9580 1.0000 1.0000 0.2933

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

IMPORTANTE: Quando operadores & e | são usados em sentenças escalares (isto é,


comparação de número em vez de vetores) o Editor sugere a utilização dos símbolos
duplicados && e ||. Estes tem a mesma função das formas simples, mas tiram proveito da
informação de que estamos comparando apenas escalares.

8.7.2 if

O if (em português “se”) é uma estrutura de seleção na qual, dado uma


condição, se ela for verdadeira o código executa um trecho e se não for executa outro (ou
nada).

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:

1 if <Condição Booleana 1>


2 <Ação 1>
3 elseif <Condição Booleana 2>
226 Capítulo 8. MATLAB básico para Cálculo Numérico

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:

1 if <Condição Booleana 1>


2 <Ação 1>
3 else
4 if <Condição Booleana 2>
5 <Ação 2>
6 else
7 if <Condição Booleana 3>
8 <Ação 3>
9 else
10 <Ação 4>
11 end
12 end
13 end

Este código funcionaria exatamente da mesma forma e, atualmente, o MATLAB tem um


custo computacional muito semelhante para ambas. No entanto, a organização do código
fica muito pior nesta segunda forma do que usando elseif.

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

Solução: Primeiramente, vamos analisar as variáveis de entrada e saída do código


que vamos implementar. Como entrada temos apenas uma variável, o número que vamos
analisar. Como a saída será através de mensagem de texto, não temos nenhuma variável
de saída explícita (podemos adicionar uma flag se quisermos, por exemplo).

Para identificar se um número é par ou ímpar utilizamos o resto da divisão do


número dado por 2. Caso o resto seja 0 o número é par e caso contrário ele é ímpar.
A frase anterior descreve em palavras o código que queremos construir e como devemos
organizar a estrutura de seleção. O pseudocódigo disso seria algo como:

1 if (Resto da divisão por 2 for zero)


2 (Escreva que o número é par)
3 else % Caso contrário ( resto == 1)
4 (Escreva que o número é ímpar)
5 end

Antes de pensar na sintaxe da condição vamos fazer a parte da mensagem. Como


vimos, para escrever algo na tela usamos a function disp.

1 if (Resto da divisão por 2 for zero)


2 disp ( 'O numero eh par ')
3 else % Caso contrario ( resto == 1)
4 disp ( 'O numero eh impar ')
5 end

Agora, para a condição do if usamos a function mod (veja a tabela 8). Se n é a


variável de entrada então a condição fica:

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

Como o problema pede uma function, colocamos o cabeçalho (uma variável de


entrada e nenhuma de saída neste caso):
228 Capítulo 8. MATLAB básico para Cálculo Numérico

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 é:

Código 8.6 – Exemplo par ou ímpar com if.


1 function parImpar ( n )
2
3 if n >= 0 & n == fix ( n )
4 if mod (n ,2) == 0
5 disp ( 'O numero eh par ')
6 else % Caso contrario ( resto == 1)
7 disp ( 'O numero eh impar ')
8 end
9 else
10 disp ( 'O numero precisa ser inteiro e positivo . ')
11 end

8.7.3 switch

O switch (em português “escolha” ou “interruptor”) é outra estrutura de seleção


disponível. A lógica para construção é muito similar ao if, porém esta estrutura propicia
considerarmos vários casos/possibilidades para uma variável.
8.7. Estruturas de seleção e repetição 229

A estrutura geral do switch é:

1 switch <Variavel teste>


2 case <Expr case1>
3 <Ações 1>
4 case <Expr case2>
5 <Ações 2>
..
6 .
7 case <Expr caseN>
8 <Ações N>
9 otherwise
10 <Ações Otherwise>
11 end

O otherwise (em português “caso contrário”) é opcional, porém costuma ser


inserido para evitar que nenhuma condição seja atendida. Nele podemos atribuir uma
mensagem de erro, por exemplo.

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.

Solução: A ideia aqui é essencialmente a mesma do exemplo para o if. Porém,


agora temos três possibilidades de resto ao invés de duas. De fato, o código usando if
seria:

1 resto = mod (n ,3) ;


2 if resto == 0
3 disp ( ' Resto 0 ')
4 elseif resto == 1
5 disp ( ' Resto 1 ')
6 else % resto == 2
7 disp ( ' Resto 2 ')
8 end

O código usando switch é:


230 Capítulo 8. MATLAB básico para Cálculo Numérico

1 resto = mod (n ,3) ;


2 switch resto
3 case 0
4 disp ( ' Resto 0 ')
5 case 1
6 disp ( ' Resto 1 ')
7 case 2
8 disp ( ' Resto 2 ')
9 otherwise
10 disp ( ' Erro . ')
11 end

8.7.4 while

Diferente do if e do switch, o while (em português “enquanto”) é uma estrutura


de repetição. Isso quer dizer que ele serve para que possamos executar um trecho de
código mais de uma vez sem a necessidade de replicá-lo várias vezes (o que tornaria o
código péssimo de ler e muito suscetível a erros).

A estrutura geral do while é:

1 while <Condição Booleana>


2 <Ações>
3 end

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

IMPORTANTE: O número de vezes que as ações dentro do while serão realizadas


dependem da condição booleana imposta. É importante nos certificarmos que em algum
momento a condição deixará de ser verdadeira. Caso contrário, entramos no que é chamado
de loop infinito.

Muitas vezes associamos um contador ao loop para contar o número de repetições


realizadas. Isso é feito nos métodos iterativos apresentados nesta apostila. No caso destas
implementações, a condição booleana nada mais é do que o critério de parada escolhido.

Saber utilizar estruturas de repetição está intimamente ligada a capacidade de


reconhecer padrões. Por exemplo, um conjunto de pontos igualmente espaçados pode ser
construído (e armazenado em um vetor) usando uma estrutura de repetição. Se desejamos
construir um vetor com os pontos:

2.0 2.25 2.5 2.5 2.75 3.0

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:

Código 8.7 – Exemplo contador com while.


1 function msgRepetida (s , n )
2
3 k = 1;
4 while k <= n
5 disp ( s )
6 k = k + 1;
232 Capítulo 8. MATLAB básico para Cálculo Numérico

7 end

Testando o código na Janela de comandos vemos que ele funciona.

1 >> msgRepetida ( ' Texto ' ,5)


2 Texto
3 Texto
4 Texto
5 Texto
6 Texto

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.

Solução: Esta é uma situação na qual o número de repetições depende do valor de


uma determinada variável, isto é, não sabemos quantas repetições o código irá fazer8 .

O código em si é muito semelhante ao exemplo anterior. Mudamos a condição do


while para que ele saia quando n for menor que 1 e adicionamos as duas variáveis de
saída pedidas no problema.

Código 8.8 – Exemplo divisão por 2 com while.


1 function [n , k ] = dividePor2 ( n )
2
3 k = 1; % Contador .
4 while n >= 1
5 n = n /2;
6 k = k + 1; % Atualiza o contador .
7 end

Testando o código na Janela de comandos vemos que ele funciona.

1 >> [n , k ] = dividePor2 (10)


2 n =
8
Ok! Seria possível descobrir isso, mas não vamos fazer isso
8.7. Estruturas de seleção e repetição 233

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

A estrutura de repetição for realiza um conjunto de operações uma quantidade


de vezes pré-fixada. Ao contrário do while onde a quantidade de repetições dependem de
outros fatores, no for sabemos de início quantas repetições serão feitas.

A estrutura geral do for é:

1 for <Variável> = <Início>:<Passo>:<Fim>


2 <Ações>
3 end

DICA: Note que a sintaxe utilizada é exatamente a mesma da declaração de um vetor


sequencial. De fato, assim como nos vetores sequenciais, podemos omitir o passo caso ele
seja 1 (o que ocorre frequentemente ao lidar com matrizes e vetores).

A estrutura para este caso é:

1 for <Variável> = <Início>:<Fim>


2 <Ações>
3 end

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.

A expressão que define as componentes do vetor v é vi = a + ih, i = 0, . . . , n. Como


já comentado, não podemos usar o índice 0 em variáveis. Por isso, precisamos ajustar os
índices para que comecem em 1.

Se fizermos apenas vi = a + ih com i = 1, . . . , (n + 1) não obteremos o vetor


desejado pois a primeira componente do vetor será a + h e a última será a + (n + 1)h
(que é maior que b). A solução neste caso é corrigir a expressão: vi = a + (i − 1)h com
i = 1, . . . , (n + 1). Você pode conferir que agora teremos a resposta correta9 . O código pode
ser escrito como abaixo.

Código 8.9 – Exemplo vetor de passo com for - versão 1.


1 function v = criaVetorPasso (a ,b , n )
2 h = (b - a ) / n ;
3 v = zeros ( n +1 ,1) ;
4 for i = 1: n +1 % Aqui , i denota a variavel do for . Ela denota
o indice do vetor .
5 v ( i ) = a + (i -1) * h ;
6 end

Outras duas soluções possíveis seriam

Código 8.10 – Exemplo vetor de passo com for - versão 2.


1 function v = criaVetorPasso2 (a ,b , n )
2 h = (b - a ) / n ;
3 v = zeros ( n +1 ,1) ;
4 for i = 0: n
5 v ( i +1) = a + i * h ;
6 end

Código 8.11 – Exemplo vetor de passo com for - versão 3.


9
De fato, este ajuste nos índices ao passar da forma algébrica para o código é muito comum pois
frequentemente usamos o índice 0 nos algebrismos.
8.7. Estruturas de seleção e repetição 235

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;

2. Usar a function sum.

Código 8.12 – Exemplo média aritmética - versão 1.


1 function m = media ( notas )
2
3 n = length ( notas ) ;
4
5 m = 0;
6 for i = 1: n
7 m = m + notas ( i ) ;
8 end
9 m = m/n;

Código 8.13 – Exemplo média aritmética - versão 2.


236 Capítulo 8. MATLAB básico para Cálculo Numérico

1 function m = media2 ( notas )


2
3 m = sum ( notas ) / length ( notas ) ;

A function que calcula a média aritmética chama-se mean.

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

No entanto, o código v = ((1:5)^2)' obtém exatamente o mesmo resultado, é


executado mais rápido e mais simples de digitar.

IMPORTANTE: Este conceito recebe o nome de vetorização e abrange todas estratégias


que buscam tornar o código mais rápido fazendo com que ele trabalhe manipulando matrizes
e vetores ao invés de escalares.

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

Solução: A primeira forma de construir esta matriz é entendendo a relação entre


os índices e atribuindo cada valor com base nisso.
10
Esta é uma matriz muito comum no estudo de métodos numéricos para equações diferenciais parciais
pelo método de diferenças finitas.
8.7. Estruturas de seleção e repetição 237

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.

Na primeira versão deste código seguiremos como dito na própria descrição do


problema. Isto é, a matriz deve ter 2 na diagonal. Por isso, faremos um loop percorrendo
todas as linhas de A e, para cada linha, percorreremos todas as colunas (para isso precisamos
de dois for). Fazemos um teste verificando se o índice da linha é igual ao índice da coluna.
Esta parte do código fica assim:

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:

Código 8.14 – Exemplo de construção de matriz - versão 0.


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 elseif abs (i - j ) == 1
9 A (i , j ) = -1;
10 end
11 end
12 end

Esta primeira forma, apesar de ser didática, ainda é extremamente ineficiente. De


fato, podemos melhor muito o código caso percebamos algumas coisas e façamos outras
de modo vetorizado. Primeiramente, o teste para ver se i é igual a j é desnecessário
pois, quando i == j, já sabemos que iremos atribuir 2 ao elemento A(i,i). Sendo assim,
podemos reorganizar o código fazendo uma segunda versão:

Código 8.15 – Exemplo de construção de matriz - versão 1.


1 function A = constroiMatriz2 ( n )
2
3 A = zeros ( n ) ;
4 for i = 1: n
5 A (i , i ) = 2;
6 for j = 1: n
8.7. Estruturas de seleção e repetição 239

7 if abs (i - j ) == 1
8 A (i , j ) = -1;
9 end
10 end
11 end

Perceba que isso implica em evitar cerca de n2 testes if.

Podemos melhorar muito as coisas se percebemos que na verdade o que estamos


fazendo (exceto na primeira e na última linha) é atribuir o vetor [-1 2 -1] na diagonal
da matriz. Pensando desta forma, podemos usar apenas um for para percorrer da linha 2
até a linha n − 1 e fazer esta atribuição. A primeira e última linha fazemos manualmente.
O código final desta segunda forma fica:

Código 8.16 – Exemplo de construção de matriz - versão 2.


1 function A = constroiMatriz2 ( n )
2
3 A = zeros ( n ) ;
4
5 A (1 ,1:2) = [2 -1];
6 A (n ,n -1: n ) = [ -1 2];
7 for i = 2: n -1
8 A (i ,[ i -1 , i , i +1]) = [ -1 2 -1];
9 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.

8.8.1 Gráficos Bidimensionais

A forma mais básica de criarmos um gráfico no MATLAB é utilizando a function


plot. A documentação desta function descreve com detalhes as diversas formas de utilizá-
la. A ideia básica é passar dois vetores de entrada: uma para o eixo x (abscissa) e outra
para o eixo y (ordenada).

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:

1. Declarar as abscissas dos pontos. No exemplo usamos 11 pontos igualmente espaçados.

2. Declarar as ordenadas dos pontos (avaliando uma função nas abscissas, por exemplo).

3. Usar a function plot para gerar o gráfico.


8.8. Gráficos 241

Abaixo você pode ver o script e o gráfico que foi gerado.

Código 8.17 – Exemplo de gráfico 2D


com plot.
1
2 % Criando o dominio da
funcao :
3 X = 0:10;
4
5 % Calculando a funcao :
6 Y = X .^2;
7
8 % Plotando a funcao :
9 plot (X , Y )

Como mencionado, no exemplo acima, é possível mudar o estilo do gráfico alterando


cores, marcadores e traços. As tabelas 13, 14 e 15 listam as opções disponíveis. Para aplicá-
las, inserimos uma string como terceira variável de entrada na chamada da function
plot.

Comando Cor
b azul
g verde
r vermelho
c ciano
m magenta
y Amarelo
k Preto
Tabela 13 – Cores básicas para gráficos.

Exemplo 8.17 (Estilo do gráfico) Problema: Modificar o script do exemplo anterior


para que o gráfico da função aparece em vermelho, com linhas pontilhadas e os pontos
dados apareçam marcados com um asterisco.

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

Comando Tipo de Ponto Comando Tipo de Ponto


. ponto v triângulo(para baixo)
o círculo ∧ triângulo(para cima)
x X < triângulo)(para esquerda)
+ + > triângulo (para direita)
* asterisco p pentágono
s quadrado h hexágono
d losango
Tabela 14 – Tipos de marcadores para gráficos.

Comando Tipo de Linha


- linha cheia
: pontilhado
-. traço e ponto
– tracejado
sem especificar sem linha
Tabela 15 – Tipos de traços para gráficos.

Código 8.18 – Exemplo de mudança no


estilo de um gráfico.
1 X = 0:10; % Pontos do
dominio .
2 Y = X .^2; % Avalia a funcao
nos pontos .
3 plot (X ,Y , 'r *: ') % Plot da
funcao .
4 % Usamos cor vermelha ,
marcadores * e linha
pontilhada .

Em diversos momentos (comparando solução exata com aproximada ou duas


soluções aproximadas, por exemplo) é interessante apresentarmos dois gráficos na mesma
janela. Se tentarmos algo como:

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

Código 8.19 – Exemplo de dois gráficos em uma única figura.


1 >> plot (X ,Y , 'r * - - ' ,X , Y2 , 'b +: ')

se quisermos alterar a apresentação do gráfico.

A segunda opção é utilizar o comando hold on, ou hold('on'). Esta function


instrui o programa para não sobrescrever a figura e manter a que já estava plotada. Ela
é muito útil quando os dados para o gráfico são gerados dentro de um loop e plotados a
cada repetição. Neste caso, podemos fazer:

1 >> plot (X , Y )
2 >> hold on
3 >> plot (X , Y2 )

ou, usando o comando anterior aos plot,

1 >> hold on
2 >> plot (X , Y )
3 >> plot (X , Y2 )

Abaixo você encontrará uma lista básica de functions associadas à elaboração de


gráficos. Por serem de uso pontual não entraremos em detalhes sobre elas mas você pode
abrir a documentação delas.

• 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

• semilogx, semilogy e loglog: muda a escala dos eixos (só em x, só em y ou em


ambos) para logaritmo.

• grid: exibe ou remove linhas de grade paralelas aos eixos.

• title: insere um título no gráfico.

• xlabel, ylabel e zlabel: insere nome para os eixos.

• legend: inclui legenda nos gráficos.

• subplot: permite fazer mais de um gráfico na mesma janela, mas sem estar no
mesmo sistema de eixos.

• tiledlayout e nextile: Funcionamento similar ao subplot.

• fplot: plota funções 2D algébricas em um intervalo dado.

8.8.2 Gráficos Tridimensionais

Além dos gráficos bidimensionais, é possível criar gráficos tridimensionais, vídeos e


animações (interativas ou não) no MATLAB. Como estas não serão ferramentas utilizadas
nesta apostila não iremos aprofundar muito o tema.

Analogamente ao caso bidimensional, podemos fazer gráficos tridimensionais usando


a function plot3. Toda a utilização é idêntica ao 2D com a diferença, é claro, que precisamos
passar 3 variáveis de entrada (uma para x, outra para y e outra para z). Desta forma,
conseguiremos desenhar curvas no espaço.

Exemplo 8.18 Problema: Criar um script que plota a curva parametrizada (cos(t), sen(t), t),
para t ∈ [−2π, 2π].

Solução: Temos

x(t) = cos(t), y(t) = sen(t), z(t) = t.

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

Código 8.20 – Exemplo curva no espaço


com plot3.
1 t = -2* pi :0.1:2* pi ; %
Parametro .
2 x = cos ( t ) ;
3 y = sin ( t ) ;
4 z = t;
5 plot3 (x ,y ,z , 'r - ') % Plot da
curva .
6 grid on
7 xlabel ( ' Eixo x ')
8 ylabel ( ' Eixo y ')
9 zlabel ( ' Eixo z ')
10 title ( ' Grafico Helicoide ')

Além das curvas no espaço, podemos também esboçar o gráfico de superfícies.


Para isso, utilizamos as functions mesh ou surf. Elas possuem o mesmo funcionamento
diferindo apenas na aparência do gráfico.

Antes de apresentar um exemplo destas functions, podemos ver uma superfície


modelo disponível no MATLAB chamada peaks. Ao digitar o nome desta function na
Janela de comandos veremos a expressão da função usada para gerar o gráfico e será
plotado o gráfico da função. Por padrão, o MATLAB usa cores quentes para representar
regiões mais altas e cores frias para regiões mais baixas. Isso pode ser alterado de diversas
formas, mas não entraremos em detalhes quanto a isso aqui.

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π].

Solução: No caso das superfícies é necessário 3 variáveis de entrada, sendo dois


vetores com os valores de x e y e uma matriz com o valor da função em cada par (xi , yj ),
isto é:

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.

Código 8.21 – Exemplo superfície 3D com


surf.
1 x = ( - pi :0.1: pi ) ';
2 y = x;
3 Z = zeros ( length ( x ) ) ;
4 f = @( x , y ) ( cos ( x ) * cos ( y ) ) ;
5
6 for i = 1: length ( x )
7 for j = 1: length ( y )
8 Z (i , j ) = f ( x ( i ) ,y ( j ) ) ;
9 end
10 end
11 surf (x ,y , Z )
12 title ( ' Grafico de f (x , y ) = cos
( x ) cos ( y ) ')
13 xlabel ( ' Eixo x ')
14 ylabel ( ' Eixo y ')
15 zlabel ( ' Eixo z ')

Observação 8.3 Ao utilizar as functions meshc ou surfc obteremos o mesmo resultado


das functions apresentadas mas com adicional de curvas de nível da superfície.

8.9 Mensagens de erro comuns


Ao programar usando o MATLAB você se deparará com eventuais mensagens de
erro ou aviso caso seu código tenha algum problema. Na maioria das vezes estas mensagens
são autoexplicativas, porém nesta esta seção listamos algumas das mais frequentes e
sugerimos qual o problema e como corrigi-lo.
8.9. Mensagens de erro comuns 247

• 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).

• Warning: Matrix is close to singular or badly scaled. Results may be inaccurate.


RCOND = 2.202823e-18.: Muitas vezes não nos atentamos ao fato que uma matriz
precisa ser inversível (determinante diferente de zero) para tentarmos resolver um
sistema linear sem problema. Caso a matriz seja singular e tentemos resolver um
sistema, o MATLAB retornará esta mensagem11 .

• 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.

• Invalid expression. When calling a function or indexing a variable, use parentheses.


Otherwise, check for mismatched delimiters.: Reveja a linha indicada ou a logo acima
e verifique se você não esqueceu algum parenteses ou colchete.

• 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.

Figura 28 – Mensagem de aviso sobre o diretório atual no MATLAB.

• No MATLAB, se implementarmos um código no qual uma variável (matriz ou


vetor) muda de tamanho a cada passo de um loop o programa não acusará erro,
porém a variável em questão será sublinhada e uma indicação aparecerá na margem
direita do Editor. Apesar da mudança de dimensão ser possível no MATLAB, não é
recomendado fazê-la frequentemente pois reduz significantemente a performance do
código. É possível evitar este problema pré-alocando a variável na dimensão correta
usando uma matriz de zeros (gerada com a function zeros). Passando o mouse por
cima da variável ou na margem direita a mensagem que aparecerá é:

The variable ’__’ appears to change size on every loop iteration. Consider
preallocating for speed.

• Como mencionado na seção 8.7.1, podemos utilizar && e || quando as condições a


esquerda e a direita são escalares (e não um vetor/matriz de operadores lógicos).
8.10. Exemplos clássicos 249

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.

8.10 Exemplos clássicos


Nesta seção apresentamos alguns exemplos clássicos utilizados para aprender
uma linguagem. Os código não estão organizados por nível de dificuldade. Se você está
aprendendo a programar, procure tentar resolver o problema antes de ler a solução.

Exemplo 8.20 (Hello world) Problema: Criar um script que exibe a frase “Hello
World”.

Solução: Um clássico da programação. Sua implementação demanda apenas uma


linha.

Código 8.22 – Script Hello World.


1 % Script Hello World ! 1 >> helloWorld

2 2 Hello World !

3 disp ( ' 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.

Código 8.23 – Function para máximo e mínimo de vetor.


1 function [ maximo , minimo ] = maxmin ( v )
2
3 n = length ( v ) ; % Tamanho do vetor .
4
250 Capítulo 8. MATLAB básico para Cálculo Numérico

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

1 >> v = rand (5 ,1)


2 v =
3 0.8003
4 0.1419
5 0.4218
6 0.9157
7 0.7922
8 >> [ ma , mi ] = maxmin ( v )
9 ma =
10 0.9157
11 mi =
12 0.1419

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.

Dado um vetor v com componentes vi e tamanho n, vamos calcular


n
s=
X
vi .
i=1

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.

Código 8.24 – Function para somar componentes de um vetor - versão 1.


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 end

1 >> v = rand (5 ,1)


2 v =
3 0.9595
4 0.6557
5 0.0357
6 0.8491
7 0.9340
8 >> s = somatorio ( v )
9 s =
10 3.4341

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

podemos fazer o código da seguinte forma:

1 % Calcula o somatorio do inverso dos numeros ateh n .


2 function s = somatorioInverso ( n )
3
4 s = 0;
5 for i = 1: n
6 s = s + 1/ i ;
7 end

Exemplo 8.23 (Sorting) Problema: Criar uma function que recebe um vetor e ordena
os números em ordem crescente.

Solução: Este é um exemplo comum de como um problema pode ter diversas


soluções. Ordenar valores parece simples, mas pode ser complexo e lento quando a quantidade
de informações é grande. Dos diferentes métodos possíveis vamos nos focar em um dos
mais simples.

Código 8.25 – Function para ordenação de valores.


8.10. Exemplos clássicos 253

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.

Solução: Intuitivamente o humano consegue distinguir qual de três números é


maior. O processo para fazer essa análise é tão natural e imediato que não nos damos
conta de como ele funciona.

Os três algoritmos abaixo mostram formas diferentes de implementar este processo


por comparação direta. Apesar deles não serem consideravelmente diferentes, a segunda
versão é certa de 20% mais rápida e a terceira é cerca de 5% mais rápida que a segunda.

Código 8.26 – Function para máximo entre 3 valores - versão 1.


1 function m = max3 (a ,b , c )
2
3 if a > b && a > c
4 m = a;
5 elseif b > a && b > c
6 m = b;
254 Capítulo 8. MATLAB básico para Cálculo Numérico

7 else
8 m = c;
9 end

Código 8.27 – Function para máximo entre 3 valores - versão 2.


1 function m = max3v2 (a ,b , c )
2
3 if a > b
4 if a > c
5 m = a;
6 else
7 m = c;
8 end
9 elseif b > c
10 m = b;
11 else
12 m = c;
13 end

Código 8.28 – Function para máximo entre 3 valores - versão 3.


1 function m = max3v3 (a ,b , c )
2
3 m = a;
4 if b > m
5 m = b;
6 end
7
8 if c > m
9 m = c;
10 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

em que aij denotam o elemento da matriz A na linha i e coluna j. O termo acima é um


somatório e se você viu o exemplo 8.22 saberá como implementar isso. O mesmo processo
precisa ser feito para cada uma das m linhas. O código para este problema fica:

Código 8.29 – Function para produto matriz-vetor.


1 function y = matrizvetor (A , x )
2
3 [m , n ] = size ( A ) ; % Precisamos saber as dimensoes da matriz .
4
5 y = zeros (m ,1) ; % Pre - alocamos a memoria para a variavel y
para que nao seja necessario mudanca no tamanho dela .
6 for i = 1: m
7 for j = 1: n
8 y ( i ) = y ( i ) + A (i , j ) * x ( j ) ;
9 end
10 end

Podemos melhorar consideravelmente o código acima se realizarmos operações de


forma vetorizada (usando vetores e matriz ao invés de apenas escalares). Para isso, basta
perceber que a operação em (8.1) nada mais é do que um produto escalar entre uma linha
de A e o vetor x. Assim, podemos eliminar um dos for fazendo o código como abaixo.

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

Uma última observação seria a respeito da qualidade dos dados de entrada. No


código acima estamos assumindo que o número de colunas de A é igual ao número de
elementos de x. Caso isso não seja verdade podemos receber uma mensagem de erro por
causa das dimensões (veja 8.9) ou pior receber uma resposta errada sem mensagem de
erro. Para evitar este problema é possível incluir alguns testes no início da function para
testar isso.

Exemplo 8.26 (Multiplicação matriz-matriz) Problema: Criar uma function que


recebe duas matrizes A ∈ Rm×n e B ∈ Rp×q e calcula C = AB.

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

Antes de fazer todo esse processo é interessante verificarmos se as matrizes são


compatíveis. Para fazer isso colocamos um if no início comparando o número de colunas
(n) de A com o número de linhas (p) de B.

Código 8.30 – Function para produto de matrizes - versão escalar.


1 function C = matrizmatriz (A , B )
2
3 [m , n ] = size ( A ) ;
4 [p , q ] = size ( B ) ;
5
6 if n ~= p
7 disp ( ' Dimensoes nao compativeis . ')
8 end
9
10 C = zeros (m , q ) ; % 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: q % Para cada coluna da matriz .
8.10. Exemplos clássicos 257

13 for k = 1: n % Loop para o somatorio .


14 C (i , j ) = C (i , j ) + A (i , k ) * B (k , j ) ;
15 end
16 end
17 end

Mais uma vez, podemos melhorar o código um pouco vetorizando o somatório:

Código 8.31 – Function para produto de matrizes - versão vetorizada.


1 for i = 1: m % Para cada linha da matriz .
2 for j = 1: q % Para cada coluna da matriz .
3 C (i , j ) = A (i ,:) * B (: , j ) ;
4 end
5 end

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.

Código 8.32 – Function para soma de matrizes - versão 1.


1 function C = somamatriz (A , B )
2
3 [m , n ] = size ( A ) ;
4 [p , q ] = size ( B ) ;
5
6 if m ~= p || n ~= q
7 disp ( ' Dimensoes nao compativeis . ')
8 end
258 Capítulo 8. MATLAB básico para Cálculo Numérico

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

Código 8.33 – Function para soma de matrizes - versão 2.


1 function C = somamatriz2 (A , B )
2
3 dim = size ( A ) ;
4 if size ( B ) ~= dim
5 disp ( ' Dimensoes nao compativeis . ')
6 end
7
8 C = zeros ( dim ) ; % Pre - alocamos a memoria para a variavel C
para que nao seja necessario mudanca no tamanho dela .
9 for i = 1: dim (1) % Para cada linha da matriz .
10 for j = 1: dim (2) % Para cada coluna da matriz .
11 C (i , j ) = A (i , j ) + B (i , j ) ;
12 end
13 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

Definido isso precisamos encontrar uma forma de identificar se um número é primo


ou não. Uma forma seria usar o crivo de Eratóstenes. Esta não é uma opção muito boa,
mas você pode tentar implementá-la como exercício.

A estratégia mais simples é simplesmente começar em 2 e verificar se n é divisível


por cada um dos números até n − 1. Para isso esta forma podemos usar as funções de
arredondamento listadas em 8. A primeira opção é a function mod que receberá n e o
número pelo qual queremos testar a divisibilidade, isto é, mod(n,2) nos dirá o resto da
divisão de n por 2 (se o resto for 0 quer dizer que é divisível). A segunda opção é usar a
functionround testando se o arredondamento do quociente é igual a ele próprio (n/i é um
número inteiro). Os dois código abaixo apresentam estas duas formas.

Código 8.34 – Function para número primo - versão 2.


1 function flag = isprime2 ( n )
2
3 % Verificando se o numero dado eh inteiro e maior que 1.
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: n -1
10 if mod (n , i ) == 0
11 flag = 0;
12 break % Interrompe o FOR .
13 end
14 end
15 end

Código 8.35 – Function para número primo - versão 3.


1 function flag = isprime3 ( n )
2
3 % Verificando se o numero dado eh inteiro e maior que 1.
4 if n < 2 || n ~= round ( n )
260 Capítulo 8. MATLAB básico para Cálculo Numérico

5 disp ( 'O numero precisa ser inteiro e maior que 1 ') ;


6 flag = 0;
7 else
8 flag = 1;
9 for i = 2: n -1
10 a = n/i;
11 if a == round ( a )
12 flag = 0;
13 break % Interrompe o FOR .
14 end
15 end
16 end

Algumas considerações sobre os código acima:

• Na parte inicial do código incluímos um teste para verificar se o número fornecido é


maior do que 2 e inteiro.

• O comando break (em português ‘quebra”)foi utilizado para interromper o processo


caso já tenhamos verificado que n não é primo. Neste caso não é necessário testar
os demais valores de i. Este comando irá quebrar o loop de repetição no qual ele está
contido, nesta caso o for i = 2:n-1. Poderíamos ter substituído por um while
adequado.

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.

Código 8.36 – Function para número primo - versão 4.


1 function flag = isprime4 ( n )
2
3 % Verificando se o numero dado eh inteiro e maior que 1.
8.10. Exemplos clássicos 261

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.

Solução: Seja v a variável de entrada. Vamos construir um vetor v2 com os


valores sem repetição. Primeiramente, atribuímos a primeira componente de v à v2 pois
este valor é a primeira ocorrência de qualquer um deles.

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

em v2. Portanto, v2 tem sempre dimensão j-1.

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.

Código 8.37 – Function unicidade de valores de um vetor.


1 function v2 = unicidade ( v )
2
3 n = length ( v ) ;
4
5 j = 2;
6 v2 (1) = v (1) ;
7 for i = 2: n
8 flag = 1; % denota a condicao de jah estar em v2 ou nao .
9 k = 1;
10 while flag == 1 && k < j
11 if v2 ( k ) == v ( i )
12 flag = 0; % v2 jah contem v .
13 end
14 k = k + 1;
15 end
16 if flag == 1 % Soh entrarah aqui caso flag continue
sendo 1.
17 v2 (j ,1) = v ( i ) ;
18 j = j + 1;
19 end
20 end

Na linha 17 usamos v2(j,1) ao invés de apenas v2(j) para forçar v2 a ser um


vetor coluna.

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.

Solução: Relembrando, o fatorial de um número n é definido como o produto de


todos os inteiros entre 1 e n, ou seja,

n! = 1 · 2 · 3 · · · · · n.

O processo realizada no fatorial é semelhante ao somatório que já usamos em vários


códigos. Porém, é uma sequência de produtos e, portanto, recebe o nome de produtório. Os
algoritmos são semelhantes:

• Ao invés de começarmos com a s = 0, começamos com o elemento neutro do produto


p = 1;

• Ao invés de usarmos s = s + (expressao), usamos p = p*(expressao).

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.

Código 8.38 – Function para fatorial.


1 function p = fatorial ( n )
2
3 if n < 0 || n ~= fix ( n )
4 disp ( 'O numero precisa ser inteiro nao negativo . ')
5 elseif n > 0
6 p = 1;
7 for i = 1: n
8 p = p*i;
9 end
10 else % n == 0
11 p = 1;
12 end

Curiosidade: O fatorial é um exemplo clássico onde podemos utilizar uma técnica


chamada de recursão. Esta consiste em chamar uma function dentro dela mesma. Abaixo
você pode ver a versão do fatorial usando recursão.
264 Capítulo 8. MATLAB básico para Cálculo Numérico

Código 8.39 – Function para fatorial - versão recursiva.


1 function p = fatorialRec ( n )
2
3 if n < 0 || n ~= fix ( n )
4 disp ( 'O numero precisa ser inteiro nao negativo . ')
5 else
6 if n > 0
7 p = n * fatorial (n -1) ;
8 else % n == 0
9 p = 1;
10 end
11 end

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.

Solução: Como sabemos, a área do círculo de raio r é A = πr2 . Essencialmente,


o que a function precisa fazer é calcular esta quantia.

Porém, além desse cálculo, é interessante testarmos se r > 0. Vamos incluir um


teste e uma mensagem de aviso caso o valor de r não seja positivo. Os dois códigos abaixo
implementam a solução deste problema apenas alterando as condições.

Código 8.40 – Function para área de círculo - versão 1.


1 function a = areacirculo ( r )
2
3 if r > 0
4 a = pi * r ^2;
5 else
6 disp ( 'O raio deve ser um numero positivo . ')
7 a = NaN ;
8 end

Código 8.41 – Function para área de círculo - versão 2.


8.10. Exemplos clássicos 265

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

Ao entrar no caso em que r ≤ 0 precisamos ainda atribuir um valor para a pois


esta é a variável de saída e não pode ficar sem informação. Por isso, optamos por atribuir
uma resposta neutra NaN.
267

Referências

1 RUGGIERO, M.; LOPES, V. da R. Cálculo numérico: aspectos teóricos e


computacionais. Pearson Makron Books, 1996. ISBN 9788534602044. Disponível em:
<https://books.google.com.br/books?id=kuRDAAAACAAJ>. Citado na página 17.

2 BURDEN, R.; FAIRES, D. Análise Numérica. Cengage Learning, 2013.


Tradução da 8a edição norte-americana. ISBN 9788522106011. Disponível em:
<https://books.google.com.br/books?id=mEo1tAEACAAJ>. Citado na página 53.

3 FRANCO, N. B. Ca?lculo numérico. Sa?o Paulo: Pearson, 2006. ISBN 9788576050872.


Citado na página 53.

4 ARENALES, S.; DAREZZO, A. Cálculo numérico: aprendizagem com apoio


de software. Cengage Learning, 2017. ISBN 9788522106028. Disponível em:
<https://books.google.com.br/books?id=WdtfOwAACAAJ>. Citado na página 53.

Você também pode gostar