Baixe o app para aproveitar ainda mais
Prévia do material em texto
Universidade Estadual De Campinas Faculdade De Tecnologia Projeto da disciplina ST468/ST462 Cálculo numérico Professor: Michael Macedo Diniz Mário Cesar Mendes Filho RA: 103457 Andreia Aparecida de Castro Aves RA: 116142 Guilherme Dornelas da Costa RA: 106699 1. Erros numéricos 1.1 Representação Faça um programa para calcular S1 e S2 = 30000 *0.11. Teoricamente os resultados deveriam ser os mesmos, isto é S1 = S2. Na prática isto não é verdade, explique o motivo da diferença entre S1 e S2. format long %Mostra aproximadamente 15 dígitos significativos x = 0.11; %Declara a variável x com o valor inicial de 0.11 S1=0; %Declara a variável z com o valor inicial de 0 for i=1:30000 %Loop para calcular a soma 30000 vezes S1=S1+x; end S1 %mostra o valor da saída Resultado: S1 = 3.300000000000629e+003; S2 = 30000 * 0.11 = 3300; %mostra o valor da saída Diferença: S1-S2 = 6.284608389250934e-010; A diferença de S1 e S2 pode ter ocorrido em função da base utilizada, da forma como os números são armazenados, ou em virtude dos erros cometidos nas operações aritméticas. O conjunto dos números representáveis em qualquer máquina é finito, e portanto, discreto, ou seja não é possível representar em uma máquina todos os números de um dado intervalo [a,b]. A representação de um número depende da BASE escolhida e do número máximo de dígitos usados na sua representação. Questão 1.2 Código 1 clear all; % limpa as variáveis armazenadas clc; %comando para limpar a tela syms x % cria uma variável simbólica para usar a função de derivada f(x)=exp(x); % função de e^x k=0; %inicia a variável k com valor 0 n=20; %variável que define o número de passos do loop “for” x0=0; %valor do ponto que a série de Taylor será calculada x1=2; %valor da variável x da função e^x if n<=170 %condição para verificação de k! for i=1:n+1 %loop que conta de 1 a n+1 g(i)=f(x0); % vetor que recebe os valores da função f(x) e suas respectivas derivadas y(x)=diff(f(x)); % a variavel y recebe a derivada de f(x) f(x)=y(x); % f(x)recebe o valor da derivada t(i)=factorial(i-1); %calcula a fatorial do indice no momento de n=i-1 v(i)=(x1-x0)^(i-1); % v(i) recebe um valor da função k=k+((g(i)/t(i))*v(i)); % calculo de séries de Taylor da respectiva função end %fim do loop 'for' double(k) else disp('overflow de k'); end a) Teste seu programa com vários valores de x (x próximo de zero e x distante de zero) e, para cada valor de x, teste o cálculo da série com vários valores de n. Analise os resultados obtidos. Até qual valor de n é possível rodar o programa? Por que o programa não roda para valores de n muito grandes? R. n = 1 n = 10 n = 100 n = 1000 n = 10000 x = 1 2 2.7183 2.7183 overflow overflow x = 10 11 1.2842e+04 2.2026e+04 overflow overflow x = 100 101 3.0582e+13 1.4155e+43 overflow overflow x = 1000 1001 2.7835e+23 1.1904e+142 overflow overflow x = 10000 10001 2.7585e+33 Inf overflow overflow É possível rodar o programa para n até 169. O programa não roda pra valores muito grandes de n, pois n determina o numero de termos da série de Taylor e para valores muito grandes o ocorre overflow da variável k devido ao fato de esta realizar o fatorial de um numero muito grande. b) O cálculo de k! necessário na série de Taylor pode ser feito de modo a evitar a ocorrência de overflow. Estude e apresente uma maneira de realizar esta operação de modo a evitar que k! estoure. Código 2 x=10; %valor de x na função exponencial n=200; %numero loops do for G=1/2; %variável inicia com valor de 0,5 V=0; %inicialização de variável for i=3:n %loop de 3 a n Z= G*(1/i); %função que realiza o calculo de k! K= Z*(x^i); % multiplica k! pelo valor numerador da função V=V+K; %soma o valor obtido da linha anterior a cada loop em V G=Z; %atualiza o valor G a cada loop end %fim do loop U= 1+x+((x^2)/2)+V %formula de Taylor para o exponencial 3. Com a modificação do item anterior, a série de Taylor pode ser calculada com quantos termos se queira. Qual seria um critério de parada para se interromper o cálculo da série? R. Um critério de parada para o código seria determinar uma precisão mínimas entre as iterações. 2.1 Método da secante e o método da bissecção Escreva um programa para calcular as raizes de uma função f(x). Inicialmente o programa deverá utilizar o método da bissecção até atingir uma precisão de e = 10^3. Posteriormente o programa deverá utilizar o método da secante para se aproximar da solução com uma precisão e = 10^8. a) Teste o seu programa com os casos abaixo. Para cada caso apresente o gráfico da função, o valor da raiz encontrado e a quantidade de iterações realizadas. Primeiro Caso Função f(x): function y = func(x) %declaração de função para a f(x) y = (x/2) - tan(x) + 0.5; %f(x) end Código: clear all clc a = -1; %inicio do intervalo onde está a raiz desejada b = 1; %fim do intervalo onde está a raiz desejada x= (a+b)/2; %metade do intervalo E = 10^-3; %precisão para o primeiro método k = 0; %contador for i=1:100 %loop de 1 a 100 if (b-a)< E && func(x)< E %condição de parada do loop x break else k = k+1; %contando as iterações M=func(a); %atribui a M o valor de f(a) x= (a+b)/2; %divide o intervalo em 2 fx = func(x); %atribui a fx o valor de f(x) if M*func(x)>0; %verifica se M vezes f(x) é maior que 0 a=x; else b=x; end end end e = 10^-8; %precisão para o segundo método for i=1:100 %loop de 1 até 100 if abs(func(x))<e %verifica se f(x) é menor que a precisão x break else x = b -((func(b)*(b-a))/(func(b)-func(a))); % Calcula um x mais próximo da raiz a=b; b=x; end end fplot('func(x)',[-1,1]) %plota o gráfico da função no intervalo de -1 a 1 title('Gráfico da função f(x)') %intitula o gráfico xlabel('x') %nomeia o eixo x ylabel('f(x)') %nomeia o eixo y grid %exibe grade no gráfico Figura 1. Gráfico da f(x) para o intervalo [-1,1] Resultados: A raiz para o primeiro método (bissecção) foi 0.7060546875 e levou um total de 11 iterações. A raiz para o segundo método (secante) foi 0.706328089467140 e levou um total de 3 iterações. Segundo Caso Função f(x): function y = func(x) %declaração de função para a f(x) y = 2*cos(x) - (exp(x)/2); %f(x) end Código: clear all clc a = 0; %inicio do intervalo onde está a raiz desejada b = pi; %fim do intervalo onde está a raiz desejada x= (a+b)/2; %metade do intervalo E = 10^-3; %precisão para o primeiro método k = 0; %contador for i=1:100 %loop de 1 a 100 if (b-a)< E && func(x)< E %condição de parada do loop x break else k = k+1; %contando as iterações M=func(a); %atribui a M o valor de f(a) x= (a+b)/2; %divide o intervalo em 2 fx = func(x); %atribui a fx o valor de f(x) if M*func(x)>0; %verifica se M vezes f(x) é maior que 0 a=x; else b=x; end end end e = 10^-8; %precisão para o segundo método for i=1:100 %loop de 1 até 100 if abs(func(x))<e%verifica se f(x) é menor que a precisão x break else x = b -((func(b)*(b-a))/(func(b)-func(a))); % Calcula um x mais próximo da raiz a=b; b=x; end end fplot('func(x)',[0,pi]) %plota o gráfico da função no intervalo de 0 a pi title('Gráfico da função f(x)') %intitula o gráfico xlabel('x') %nomeia o eixo x ylabel('f(x)') %nomeia o eixo y grid %exibe grade no gráfico Figura 2 Gráfico e f(x) para o intervalo [0,pi] Resultados: A raiz para o primeiro método (bissecção) foi 0.904665169655557 e levou um total de 13 iterações. A raiz para o segundo método (secante) foi 0.904788217871403 e levou um total de 3 iterações. 2.2 Sequências oscilantes Analise algebricamente e geometricamente e encontre justificativas para o comportamento do método de Newton quando aplicado à equação P3(x) = -0,5x^3 +2,5x = 0 nos casos onde x0 = 1 e x0 = -1. Dica: Plote o gráfico da função f(x) para entender o comportamento do método de Newton para este caso. Código: Função da derivada de f(x): function z = dev(x) %declaração de função para derivada de f(x) z = -1.5*x^2 + 2.5; %derivada de f(x) end Função f(x): function y = func(x) %declaração de função para a f(x) y = -0.5*x^3 + 2.5*x; %f(x) end Método de Newton: clear all %limpa todas as variáveis clc %limpa a janela de comando x0 = 1; %inicializa um valor próximo a raiz e = 10^-4; %defini uma variável para a precisão for i=1:100 %inicio do loop de 1 a 100 iterações if abs(func(x0)) < e && abs(x1-x0) < e %condição de parada para o loop x0 break else x1 = x0 - (func(x0)/dev(x0)); %é atribuído o valor de x0 menos o %valor da função em x0 dividido pela derivada em x0 a variavel x1 x0=x1; %é atribuído o valor de x1 a x0 end end fplot('func(x)', [-3,3]) %plota o gráfico da função no intervalo de -3 a 3 title('Gráfico da função f(x)') %intitula o gráfico xlabel('x') %nomeia o eixo x ylabel('f(x)') %nomeia o eixo y grid %exibe grade no gráfico Figura 3. Gráfico de f(x) para o intervalo (-3,3). 3.1 Fatoração LU clear all; % limpa os valores das variaveis clc;% limpa a tela A= [3 2 4; 1 1 2; 4 3 -2]; %valores da matriz A B= [1;2;3]; % valor da coluna dos coeficientes U=[A,B];% U recebe a matriz aumentada da concatenação de A e B [L,C]= size(U); %indices contendo os valores de quantas linhas e colunas que U possui for k=1:L-1 %laço for de indice k de 1 até L-1 for i=k+1:L %laço for de indice i de 1+k até L-1 m(i,k)=(U(i,k)/U(k,k)); % valores dos fatores m(i,k) U(i,k:C)= U(i,k:C)-(U(i,k)/U(k,k))*U(k,k:C); %algoritmo da eliminação de Gauss end end U(:,C)=[]; %retira a ultima coluna de U V= eye(size(A))+[m,zeros(size(B))]; %Concatenação de uma matriz diagonal do tamanho de A com os valores da matriz m Y=zeros (size(B)); % criação dos coeficientes de Y com valores iniciais = 0 do tamanho de B, criando assim L V=[V,B]; % concatenação da matriz L com B Y(1)= V(1,C)/V(1,1); %valor da posição de Y(1) for i= 2:size(B) %laço for de indice i de 1 até o tamanho do vetor de B Y(i)= (V(i,C)-V(i,1:i)*Y(1:i))/V(i,i); %algoritmo para calculo dos valores restantes de Y end X=zeros (size(B)); %criação dos coefiecientes da incógnita X com tamanho de B U=[U,Y]; %concatenação de U com Y X(L)= U(L,C)/U(L,L); %valor da posição de Y(L) for i= L-1:-1:1 %laço for de indice i de L-1 até 1 com contagem decrescente X(i)=(U(i,C)-U(i,i:L)*X(i:L))/U(i,i); %algoritmo para calculo dos valores restantes de X end 3.2 Métodos Iterativos Implemente o método de Gauss-Seidel através de um programa computacional. clear all; clc; A= [10 1 1;1 10 1;1 1 10];%valores da matriz A B= [12;12;12];% valor matriz coluna ab=[-A,B];% ab recebe a matriz aumentada da concatenação de -A e B [L,C]= size(ab);%indices contendo os valores do tamanho de ab X= [0 0 0]; %inicialização de X X=[X,1]; %concatena X com 1 Y= zeros(size(B)); % cria um vetor Y do tamanho de B contendo zeros X=X'; %transposta de X n=0; v=0; k=0; while(v==0) %enquanto a v é zero if (n >= 1) %se n for maior ou igual a 1 if X(1:C-1)== Y; %se o vetor X for igual ao vetor Y v=v+1; %incrementa v else k=k+1; % contador aumenta 1 Y=X(1:C-1); % vetor Y recebe os valores de X for i= 1:L %enlace de 1 até L p = -ab(i,i); %variavel p recebe os valores de ab X(i)=0; %zera os valores de X a cada loop X(i)=(ab(i,1:C)*X)/(p); %algoritmo de Gauss Seidel end end else n=n+1; for i= 1:L %Loop de 1 até L p = -ab(i,i);%variavel p recebe os valores de ab X(i)=0;%zera os valores de X a cada loop X(i)=(ab(i,1:C)*X)/(p); %algoritmo de Gauss Seidel end end end X Resultado: X = 1 1 1 Segundo Caso clear all; % limpa os valores das variaveis clc;% limpa a tela A= [4 -1 0 0;-1 4 -1 0;0 -1 4 -1; 0 0 -1 4];%valores da matriz A B= [1;1;1;1];% valor matriz coluna ab=[-A,B];% ab recebe a matriz aumentada da concatenação de -A e B [L,C]= size(ab);%indices contendo os valores do tamanho de ab X= [0 0 0 0]; %inicialização de X X=[X,1]; %concatena X com 1 Y= zeros(size(B)); % cria um vetor Y do tamanho de B contendo zeros X=X'; %transposta de X n=0; v=0; k=0; while(v==0) %enquanto a v é zero if (n >= 1) %se n for maior ou igual a 1 if X(1:C-1)== Y; %se o vetor X for igual ao vetor Y v=v+1; %incrementa v else k=k+1; % contador aumenta 1 Y=X(1:C-1); % vetor Y recebe os valores de X for i= 1:L %enlace de 1 até L p = -ab(i,i); %variavel p recebe os valores de ab X(i)=0; %zera os valores de X a cada loop X(i)=(ab(i,1:C)*X)/(p); %algoritmo de Gauss Seidel end end else n=n+1; for i= 1:L %Loop de 1 até L p = -ab(i,i);%variavel p recebe os valores de ab X(i)=0;%zera os valores de X a cada loop X(i)=(ab(i,1:C)*X)/(p); %algoritmo de Gauss Seidel end end end X Resultado: X = 0.3636 0.4545 0.4545 0.3636 4.1 Interpolação Calcule o valor aproximado de x tal que f(g(x)) = 0,6, usando polinômios interpolantes de grau 2. Código: clear all clc w=[0.1 0.2 0.4 0.6 0.8 0.9]; %vetor w fw=[0.905 0.819 0.67 0.549 0.449 0.407]; % vetor f(w) a=0; %inicialização de variável a2=0; %inicialização de variável a3=0; %inicialização de variável fgx=0.6; %valor de f(g(x)) for k=3:5 %primeiro loop de 3 a 5 a1=1; %variavel a1 recebe valor 1 for i=3:5 %segundo loop de 3 a 5 if i~= k %verifica se i é diferente de k a=a1*(fgx-fw(i))/(fw(k)-fw(i)); %principal linha do algoritmo de Lagrange a1=a; %a1 recebe o valor de a end end a2=w(k)*(a)+a3; %a2 recebe o valor da operação no loop a3=a2; %a3 recebe o valor de a2 end a3 x=[1 1.2 1.4 1.7 1.8]; %vetor x gx=[0.210 0.320 0.480 0.560 0.780]; %vetor g(x) b=0; %inicialização de variável b2=0; %inicialização de variável b3=0; %inicialização de variável for k=3:5 %primeiro loop de 3 a 5 b1=1; %variavel b1 recebe valor 1 for i=3:5 %segundo loop de 3 a 5 if i~= k %verifica se i é diferente de k b=b1*(a3-gx(i))/(gx(k)-gx(i)); %principal linha do algoritmo de Lagrange b1=b; %b1 recebe o valor de b end end b2=x(k)*(b)+b3; %b2 recebe o valor da operação no loop b3=b2; %b3 recebe o valor de b2 end b3 Resultados: a3 = 0.5101 b3 = 1.5294 Onde a3 é igual a g(x) e b3 é igual a x. 4.2 Método dos quadrados mínimos Código: clear all clc %% Entrada de dados syms x x1= [158 163 163 168 173 178 183 188 193]; %altura y= [61 63 71 70 69 7379 81 79]; % peso C= size(x1,2); z=[]; z1=[]; f1(x)=x; f2=1; aux=0; aux1=0; aux2=0; %% Algoritmo (metodo dos quadrados minimos) for i=1:2 for j=1:2 if i==1 && j==1 for k=1:C z(i,j)=(f1(y(k))* f1(y(k)))+aux; aux=z(i,j); z1(i,j)= (x1(k)*f1(y(k)))+ aux1; z1(i+1,j)= (x1(k)*f2)+ aux2; aux2= z1(i+1,j); aux1=z1(i,j); end end aux=0; k=0; if i==1 && j==2 || i==2 && j==1 for k=1:C z(i,j)=(f1(y(k))*f2)+aux; aux=z(i,j); end end k=0; aux=0; if i==2 && j==2 for k=1:C z(i,j)=(f2*f2)+aux; aux=z(i,j); end end k=0; aux=0; end end z3= [z,z1]; [L,C]= size(z3); %indices contendo os valores de quantas linhas e colunas que U possui for k=1:L-1 %laço for de indice k de 1 até L-1 for i=k+1:L %laço for de indice i de 1+k até L-1 m(i,k)=(z3(i,k)/z3(k,k)); % valores dos fatores m(i,k) z3(i,k:C)= z3(i,k:C)-(z3(i,k)/z3(k,k))*z3(k,k:C); %algoritmo da eliminação de Gauss end end X=zeros (size(z1)); %criação dos coefiecientes da incógnita X com tamanho de B X(L)= z3(L,C)/z3(L,L); %valor da posição de Y(L) i=0; for i= L-1:-1:1 %laço for de indice i de L-1 até 1 com contagem decrescente X(i)=(z3(i,C)-z3(i,i:L)*X(i:L))/z3(i,i); %algoritmo para calculo dos valores restantes de X end f3(x)= X(1)*x + X(2); x = (175-X(2))/X(1) z = (80*X(1)) + X(2) double (f3(y)); %% Diagrama de Dispersão plot( y,f3(y)) hold on plot (y,x1,'o') legend('Interpolação' ,'Dispersão') grid Resultados: x = 72.3384 z = 187.1489 O peso estimado de um funcionário de 175 cm é 72,3384 Kg e a altura estimada de um funcionário de 80 Kg é 187,1489 cm. Figura 4 Gráfico do ajuste de curva 5. Método de Simpson e método dos Trapézios a) Calcular usando o método dos trapézios. Função f(x): function y = funcao(x) %declaração de função para a f(x) y =1/(1+x); %f(x) end clear all; clc; x=[]; %inicia vetor x vazio a=0.6; %limite superior da integral b=0; %limite inferior da integral n=12; %numero de trapézios z=0; %variável auxiliar h=(a-b)/n; %altura dos trapézios for i=1:1:n+1 %loop de 1 até n+1 x(i) = ((a-b)/n) *z; %preenche o vetor x z=i; %z recebe o valor de i a cada enlace end i=0; z=0; for i=1:1:n %loop de 1 até n y = ((funcao(x(i))+funcao(x(i+1)))*0.5*h) +z; %operação que calcula as áreas dos trapézios z = y; %z recebe o valor de y a cada enlace end z Resultado: = 0.4701 b) Calcular usando o método de Simpson Função f(x): function y = funcao(x) %declaração de função para a f(x) y =1/(1+x); %f(x) end clear all clc x=[]; %inicializa vetor x vazio a=0.6; %limite superior da integral b=0; %limite inferior da integral n=6; %numero de subintervalos h=(a-b)/n; %distancia dos subintervalos %laço que preenche o vetor x com os valores da função para cada %subintervalo for i=1:1:n x(i)= funcao(i*h); end i=0; w=0; %laço que soma os índices pares do vetor x for i=2:2:n-1 y1= (x(i)) +w; w=y1; end i=0; k=0; %laço que soma os índices ímpares do vetor x for i=1:2:n-1 y2=(x(i)) +k; k=y2; end %Equação geral que nos fornece a integral pela Regra de Simpson I = (h/3)*(2*w + 4*k + funcao(a)+ funcao(b)) Resultado: = 0.4700 c) Calcular usando o método dos trapézios. Função f(x): function y = funcao(x) %declaração de função para a f(x) y =exp(sin(x)); %f(x) end clear all; clc; x=[]; %inicia vetor x vazio a=pi; %limite superior da integral b=0; %limite inferior da integral n=50; %numero de trapézios z=0; %variável auxiliar h=(a-b)/n; %altura dos trapézios for i=1:1:n+1 %loop de 1 até n+1 x(i) = ((a-b)/n) *z; %preenche o vetor x z=i; %z recebe o valor de i a cada enlace end i=0; z=0; for i=1:1:n %loop de 1 até n y = ((funcao(x(i))+funcao(x(i+1)))*0.5*h) +z; %operação que calcula as áreas dos trapézios z = y; %z recebe o valor de y a cada enlace end z Resultado: = 6.2081 c) Calcular usando o método de Simpson Função f(x): function y = funcao(x) %declaração de função para a f(x) y =exp(sin(x)); %f(x) end clear all clc x=[]; %inicializa vetor x vazio a=pi; %limite superior da integral b=0; %limite inferior da integral n=6; %numero de subintervalos h=(a-b)/n; %distancia dos subintervalos %laço que preenche o vetor x com os valores da função para cada %subintervalo for i=1:1:n x(i)= funcao(i*h); end i=0; w=0; %laço que soma os índices pares do vetor x for i=2:2:n-1 y1= (x(i)) +w; w=y1; end i=0; k=0; %laço que soma os índices ímpares do vetor x for i=1:2:n-1 y2=(x(i)) +k; k=y2; end %Equação geral que nos fornece a integral pela Regra de Simpson I = (h/3)*(2*w + 4*k + funcao(a)+ funcao(b)) Resultado: = 6.2086 Conclusão: Através dos conhecimentos que adquirimos em sala de aula percebemos a importância dos métodos numéricos para se resolver problemas, que até então não tinham soluções analíticas, o que nos mostra o grande avanço que o cálculo numérico proporciona em nossas vidas. Ao implementarmos códigos como esses, vimos como os métodos numéricos facilitam a resolução de problemas difíceis, mas comuns no cotidiano da engenharia e matemática, que por consequência afetam a vida de todos através de suas aplicações tecnológicas.
Compartilhar