Mais for para nós
INF01202
Sumário
Laços iterativos (loops)
I Erros frequentes no comando for
I Comandos for aninhados
I Mais fatorial e bonacci
I Tamanho do tipo int em fatorial e bonacci
I Mais estudos de caso
1. Tabuada
2. Estimar a raiz quadrado de 2 por Newton-Raphson
3. Maior e menor
4. Estimar a exponencial de um número
I Miscelânea
Erros frequentes (ponto e vírgula acidental)
12 INF 01202 - Prof. Marcelo Walter – Aula 08 /* Mostra erros comuns no uso do comando for */ #include <stdio.h>
int main() {
int i,soma=0; for (i=0; i<100; i++); soma = soma + i; return(0); } • O ; conclui o comando: repetições de nada. • Usado para gerar
tempos de espera.
Comando for – erros frequentes
Loop sem conteúdo (por engano de pontuação)
Erros frequentes (esquecimento de bloco)
13 INF 01202 - Prof. Marcelo Walter – Aula 08 /* Mostra erros comuns no uso do comando for */ #include <stdio.h>
int main() {
int i, soma; for (i=0; i < 100; i++) soma = soma + i;
printf(“\n%d termo vale %d”,i, soma); return(0);
}
Comando for – erros frequentes
• Sem { } depois do for: indica comando simples; • Apenas o 1º. comando é
repetido! • Indentação é para auxiliar o programador, ignorada pelo compilador!!
Loop de apenas 1 comando (por falta de { } )
Erros frequentes (laços innitos)
14 INF 01202 - Prof. Marcelo Walter – Aula 08
Qual o problema com os programas abaixo? //programa de teste #include <stdio.h> int main ( ) { int i; for (i = 5; i < 10 ; i--) printf("\n%d", i); return 0; } //programa de teste #include <stdio.h> int main ( ) { int i, j=2; for (i = 1; i < j ; i++){ printf("\n%d %d", i,j); j++; } return 0; } Loop (laço) infinito!!!!
Estudo de caso do fatorial (aninhar laços for)
Ao invés de calcular o fatorial de um número, calcular o fatorial de todos os números até um número informado.
Entrada: um número inteiro positivo
Estudo de caso do fatorial (aninhar laços for)
Ao invés de calcular o fatorial de um número, calcular o fatorial de todos os números até um número informado.
Entrada: um número inteiro positivo
Tomando por base o exemplo anterior
Quais alterações são necessárias?
I Repetir o cálculo para todos os números até o informado #include <stdio.h>
int main () {
int num, fat, i;
printf("Entre um numero inteiro positivo: " ); scanf("%d", &num);
if (num < 0)
printf("Tsk tsk, o número informado é negativo.\n"); else {
//o que fazer aqui para resolver nosso objetivo? fat = 1; // se for zero, está pronto
for (i= num; i >= 1; i--) fat = fat * i;
printf ("Fatorial de %d eh %d.\n", num, fat); }
return 0; }
Uma primeira possível solução
#include <stdio.h>
int main () {
int num, fat, i, j;
printf("Entre um numero inteiro positivo: " ); scanf("%d", &num);
if (num < 0)
printf("Tsk tsk, o número informado é negativo.\n"); else {
for (j = 0; j <= num; j++) {
fat = 1; // se for zero, está pronto for (i = j; i >= 1; i--)
fat = fat * i;
printf ("Fatorial de %d eh %d.\n", j, fat); }
}
return 0; }
Para a entrada 10, o programa calcula 10Ö9Ö8Ö7Ö6Ö5Ö4Ö3Ö2Ö1. Mas esta é uma boa solução?
Uma primeira possível solução
#include <stdio.h>
int main () {
int num, fat, i, j;
printf("Entre um numero inteiro positivo: " ); scanf("%d", &num);
if (num < 0)
printf("Tsk tsk, o número informado é negativo.\n"); else {
for (j = 0; j <= num; j++) {
fat = 1; // se for zero, está pronto for (i = j; i >= 1; i--)
fat = fat * i;
printf ("Fatorial de %d eh %d.\n", j, fat); }
}
return 0; }
Para a entrada 10, o programa calcula 10Ö9Ö8Ö7Ö6Ö5Ö4Ö3Ö2Ö1. Mas esta é uma boa solução?
Uma segunda possível solução
Para a entrada 10, o programa calcula 10Ö9Ö8Ö7Ö6Ö5Ö4Ö3Ö2Ö1. I Em cada iteração, imprimir na tela
#include <stdio.h>
int main () {
int num, fat, i, j;
printf("Entre um numero inteiro positivo: " ); scanf("%d", &num);
if (num < 0)
printf("Tsk tsk, o número informado é negativo.\n"); else { for (i = 0; i <= num; i++){ if (i == 0){ fat = 1; }else{ fat = fat * i; }
printf ("Fatorial de %d eh %d.\n", i, fat); }
}
return 0; }
Estudo de caso do bonnaci (aninhar laços for)
Ao invés de calcular o valor bonacci de uma posição, calcular tal valor para todas as posições até uma posição informada.
Entrada: um número inteiro positivo
Estudo de caso do bonnaci (aninhar laços for)
Ao invés de calcular o valor bonacci de uma posição, calcular tal valor para todas as posições até uma posição informada.
Entrada: um número inteiro positivo
Tomando por base o exemplo anterior
Quais alterações são necessárias?
I Repetir o cálculo para todos as posições até a informada #include<stdio.h>
int main(){
int pos, fib, t_1, t_2, i;
printf("Entre um numero inteiro positivo: " ); scanf("%d", &pos);
if (pos < 0) printf("Tsk tsk, a posição informada é negativa\n"); else {
//o que fazer aqui para resolver nosso objetivo? if (pos == 0) fib = 0; else if (pos == 1) fib = 1; else{ t_2 = 0; t_1 = 1; for (i = 2; i <= pos; i++){ fib = t_2 + t_1; t_2 = t_1; t_1 = fib; } }
printf ("Fibonacci da posição %d eh %d.\n", pos, fib); }
return 0;
Uma possível solução
#include<stdio.h>
int main(){
int pos, fib, t_1, t_2, i;
printf("Entre um numero inteiro positivo: " ); scanf("%d", &pos);
if (pos < 0) printf("Tsk tsk, a posição informada é negativa\n"); else { t_2 = 0; t_1 = 1; for (i = 0; i <= pos; i++){ if (i == 0){ fib = 0; }else if (i == 1){ fib = 1; }else{ fib = t_2 + t_1; t_2 = t_1; t_1 = fib; }
printf ("Fibonacci da posição %d eh %d.\n", i, fib); }
}
return 0; }
Tamanho do tipo int em fatorial e bonacci
O que acontece se testarmos Fatorial de 35? ./a08-fatorial-solucao-2.c
O que acontece se testarmos Fibonacci de 50? ./a08-fibonacci-solucao.c
Exemplo de Fibonnaci
E se usarmos o tipo long long, ou unsigned long long.
I pos(93) funciona?
Tamanho do tipo int em fatorial e bonacci
O que acontece se testarmos Fatorial de 35? ./a08-fatorial-solucao-2.c
O que acontece se testarmos Fibonacci de 50? ./a08-fibonacci-solucao.c
Exemplo de Fibonnaci
E se usarmos o tipo long long, ou unsigned long long.
I pos(93) funciona?
Comandos for aninhados
15 INF 01202 - Prof. Marcelo Walter – Aula 08
Comando:
qualquer comando, pode ser inclusive outro comandofor ! Comandos for aninhados
...
for (ka = 1; ka <= 3; ka++)
for (ele=2; ele<=8;ele= ele + 2) printf(“ka-%d - ele-%d\n”, ka,ele); ...
for (expressão 1; expressão 2 ; expressão 3 ) comando;
1 comando: simples ou composto
Vejamos o exemplo
#include <stdio.h>
int main(){
int ka, ele;
for (ka = 1; ka <= 2; ka++) for (ele=2; ele<=6;ele= ele + 2)
printf("ka -> %d -- ele -> %d\n", ka, ele); }
Funcionamento de for aninhado
16 INF 01202 - Prof. Marcelo Walter – Aula 08 Funcionamento de for s aninhados:
• Para cada variação de valor da(s) variável(eis) de controle
do FOR externo, todo oFORinternoserá executado
integralmente (como na execução completa de um comando qualquer).
• Exemplo: ...
for (ka = 1; ka <= 3; ka++) for (ele=2; ele<=8;ele= ele + 2)
printf(“ka-%d - ele-%d\n”, ka,ele); ...
Estudo de caso #1 (Tabuada)
17 INF 01202 - Prof. Marcelo Walter – Aula 08 Exercício: gerador de tabuada
Faça um programa que gere o resultado da tabuada de todos os números de 1 a 10. O resultado deve
aparecer como na tela ao lado.
Dica: use 2 comandos for aninhados: 1 para controlar os multiplicadores e outro para controlar os multiplicandos. Tabuada de 1: 1 x 1 = 1 2 x 1 = 2 3 x 1 = 3 4 x 1 = 4 5 x 1 = 5 6 x 1 = 6 7 x 1 = 7 8 x 1 = 8 9 x 1 = 9 10 x 1 = 10 Tabuada de 2: 1 x 2 = 2 2 x 2 = 4 3 x 2 = 6 4 x 2 = 8 5 x 2 = 10 6 x 2 = 12 7 x 2 = 14 8 x 2 = 16 9 x 2 = 18 10 x 2 = 20 e segue…
Cortesia: Prof. Marcelo Walter
(#1: Tabuada) Uma solução possível
/* gera a tabuada dos números de 0 a 10: Entrada: não há
Saida: impressão da tabuada na tela */ #include <stdio.h>
int main () {
int multiplicando, multiplicador;
for (multiplicador = 0; multiplicador <= 10; multiplicador++){ printf("Tabuada de %d:\n", multiplicador);
for (multiplicando = 0; multiplicando <= 10; multiplicando++) { printf("%2d x %2d = %2d\n",
multiplicando , multiplicador, multiplicando * multiplicador); }
printf("\n"); }
return 0; }
Podemos inverter os dois laços for? O que acontece se assim zermos?
(#1: Tabuada) Uma solução possível
/* gera a tabuada dos números de 0 a 10: Entrada: não há
Saida: impressão da tabuada na tela */ #include <stdio.h>
int main () {
int multiplicando, multiplicador;
for (multiplicador = 0; multiplicador <= 10; multiplicador++){ printf("Tabuada de %d:\n", multiplicador);
for (multiplicando = 0; multiplicando <= 10; multiplicando++) { printf("%2d x %2d = %2d\n",
multiplicando , multiplicador, multiplicando * multiplicador); }
printf("\n"); }
return 0; }
Podemos inverter os dois laços for? O que acontece se assim zermos?
Estudo de caso #2 (Newton-Raphson)
8 INF 01202 - Prof. Edison – Aula 08
Exercício: cálculo aproximado da raiz de 2
A raiz de 2 pode ser aproximada através do algoritmo de Newton-Raphson. Partindo de uma aproximação inicial x0, podem ser encontradas aproximações sucessivas através da equação de recorrência abaixo:
Escreva um programa em C que tenha como entrada o número de iterações (niter) e a aproximação inicial xinic(x0), e forneça como saída a aproximação para a raiz de 2 com esse número de iterações.
x
n= x
n-1-
xn-12 -22 xn-1
x
0valor inicial fornecido
ì
í
ï
îï
(#2 Newton-Raphson) Uma solução possível
/* Programa para calcular raiz quadrada de 2 usando Newton-Raphson Entrada: numero de iteracoes (inteiro) e chute inicial
Saida: valor aproximado de raiz de 2*/ #include <stdio.h>
#include <math.h>
int main() {
int niter; // Entrada: numero de iteracoes
int i; // Variável auxiliar para contar as iterações
double xinic, x1, x2; // aproximacao inicial e valores usados na iteracao
printf("Entre o numero de iteracoes:\n"); scanf("%d", &niter);
printf("Entre a aproximacao inicial de raiz de 2:\n"); scanf("%lf", &xinic);
x1 = xinic;
for (i = 0; i < niter; i++) { x2 = x1 - (x1*x1-2)/(2*x1);
printf("Em iteração %d, valor aproximado é %1.15f\n", i, x2); x1 = x2; } printf("sqrt(2) : %1.15f\n" "Valor aproximado: %1.15f\n", sqrt(2), x2); return 0; }
Estudo de caso #3 (Maior-Menor)
11 INF 01202 - Prof. Edison – Aula 08 Exercício
Faça um programa para ler uma sequencia de 5 inteiros
que apresente ao final o maior e o menor dos valores lidos.
Idéia de solução: inicializamos uma variável menor com o maior valor possível e vice-versa.
À medida que vamos lendo os valores, verificamos se o novo valor lido satisfaz ou não o critério de maior ou menor e trocamos se for o caso
(#3 Maior-Menor) Uma solução possível com 4 números
#include <stdio.h> #include <limits.h> #define ELEM 4
int main (){
int i, num, maior = INT_MIN, menor = INT_MAX;
printf("No início: %d (menor), %d (maior)\n", menor, maior); for(i = 0; i < ELEM; i++){
printf("Entre com o numero %d: ", i); scanf("%d", &num);
if (num > maior) maior = num; if (num < menor) menor = num;
printf("Iteração %d, até agora: %d (menor), %d (maior)\n", i, menor, maior); }
printf("O menor numero eh %d, e o maior eh %d\n", menor, maior); return 0;
}
(#3 Maior-Menor) Uma solução possível com 4 números
#include <stdio.h> #include <limits.h> #define ELEM 4
int main (){
int i, num, maior = INT_MIN, menor = INT_MAX;
printf("No início: %d (menor), %d (maior)\n", menor, maior); for(i = 0; i < ELEM; i++){
printf("Entre com o numero %d: ", i); scanf("%d", &num);
if (num > maior) maior = num; if (num < menor) menor = num;
printf("Iteração %d, até agora: %d (menor), %d (maior)\n", i, menor, maior); }
printf("O menor numero eh %d, e o maior eh %d\n", menor, maior); return 0;
}
Estudo de caso #4 (Série de potência)
13 INF 01202 - Prof. Edison – Aula 08
Exercício: séries de potências
Várias funções matemáticas podem ser escritas através de séries de potências. Por exemplo, para qualquer número real x, a exponencial de x pode ser calculada via:
Podemos truncar a série, ou seja, definir uma quantidade finita de termos, e calcular a exponencial de forma aproximada usando essa quantidade de termos.
Escreva um programa em C que tenha como entrada o número de termos, o valor de x, e retorne como saída a aproximação da função exponencial com essa quantidade de termos.
ex= xn n!= n=0 +¥
å
x0!0+ x 1!+ x 2 2!+ x 3 3!+ x 4 4!+...(#4 Série de potência) Uma solução possível
/* Programa para calcular exp(x) de forma aproximada, via series depotencias
Entradas: valor de x e numero de termos a serem usados na série Saída: valor aproximado de exp(x) */
#include <stdio.h>
#include <math.h>
intmain() {
intn; // Entrada: numero de termos doublex; // Entrada: valor de x doubleexp_x; // Saída: exponencial de x doubletermo; // variavel auxiliar inti, cont_fat; // contadores long longfat; // fatorial
printf("Entre o valor x e o numero de termos da serie:\n"); scanf("%lf%d",&x,&n);
exp_x= 0;
for(i= 0; i<n; i++) { {
fat= 1;
for(cont_fat=i; cont_fat>= 1; cont_fat--) fat=fat*cont_fat;
}
termo=pow(x, i)/fat;// calcula o termo
exp_x=exp_x+termo;// atualiza valor do somatorio
printf("Na iteração %d, valor %lf\n", i, exp_x); }
printf("Valor calculado : %lf\n", exp_x); printf("Valor de exp(%2.f): %lf\n", x, exp(x));
return0; }
(#4 Série de potência) Compilação & Execução
gcc a08-serie-potencia.c -lm; echo "2 14" | ./a.out gcc a08-serie-potencia.c -lm; echo "3 6" | ./a.out
Inicializações ou incrementos / decrementos múltiplos
27 INF 01202 - Prof. Edison – Aula 08
Inicializações ou incrementos / decrementos múltiplos:
• Em um comandoforpodem ser feitas mais de uma inicializaçãoe/ou
mais de um incremento/decrementode variáveis: a vírgulaé o separador utilizado internamente a cada porção do comando • Ex.:
//inicializações: j = 1 e i = 10
// incremento e decremento:j = j + 2 e i = i-1
// condição de execução:enquanto i > 0
//comando for:
for (j = 1,i = 10; i > 0; j = j + 2,i--) {
// comandos }
Comando de repetição for
Exemplo
28 INF 01202 - Prof. Edison – Aula 08 //for usando duas variáveis #include <stdlib.h> int main ( ) { int i, j; for (i = 1, j = 10;i<= 10; i++, j--) printf("\ni = %4d j = %4d", i , j); printf("\n\n"); return (0); } Execução: Exemplos Utilização de mais de uma variável de controle no comando for
Exercício #1 (Newton-Raphson com erro)
14 INF 01202 - Prof. Marcelo Walter – Aula 09
Exercício: cálculo aproximado da raiz de 2 Agora usando do-while
Vimos na aula passada que a raiz de 2 pode ser aproximada através do algoritmo de Newton-Raphson. Partindo de uma aproximação inicial x0, podem ser encontradas aproximações sucessivas através da equação de recorrência
Escreva um programa em C que tenha como entradas a aproximação inicial xinic (x0) e uma tolerância tol para o erro, e forneça como saída a aproximação para a raiz de 2 com esta tolerância. A tolerância expressa o erro mínimo a ser obtido entre duas parcelas sucessivas.
xn= xn−1− xn−12 −2 2 xn−1
x0 valor inicial fornecido "
# $ %$
Exercício #2 (Taxa de Crescimento)
21 INF 01202 - Prof. Marcelo Walter – Aula 09 Exercício
n O Brasil, com 203 milhões de habitantes, cresce a uma
taxa anual de 1.5% enquanto os Estados Unidos com 318 milhões crescem a uma taxa anual de 1.3%.
n Calcule o número de anos que levará para o Brasil
ultrapassar os Estados Unidos em número de habitantes, considerando-se que a cada ano a taxa dos Estados Unidos diminua em 0.1%. A taxa nunca fica negativa, no máximo a população permanece a mesma.
n Resposta: 37anos
http://data.worldbank.org/indicator/SP.DYN.CBRT.IN http://en.wikipedia.org/wiki/List_of_countries_by_population
Fonte dos dados: