Gilson de Souza Carvalho gaucho.gilson@hotmail.com 1
Comandos de repetição combinados com comandos de condição A utilização de comandos de repetição combinados com comandos de condição permite resolver problemas bem mais complexos que os vistos até agora. Na realidade, o ferramental já apresentado é a base para toda a sequência de algoritmos, e sua compreensão é absolutamente fundamental para o desenvolvimento de algoritmos mais sofisticados. 2
Os comandos de condição podem fazer parte de blocos pertencentes a comandos de repetição e vice-versa. Ou seja, estruturas como as descritas a seguir podem ocorrer intercaladas quantas vezes forem necessárias. 3
if <valor boolean> { while <valor boolean> { } } //} do bloco if 4
} else { while <valor boolean> { if <valor boolean> { } else { } } //} do bloco while } //} do bloco else} <continuação do algoritmo> 5
Na estrutura anterior temos comandos de decisão aninhados a comandos de repetição e vice-versa. Esse tipo de estrutura é extremamente útil para resolver problemas em diversas situações. Vejamos a seguir alguns exemplos. 6
Calcular a soma dos números ímpares de um intervalo Faça um algoritmo que calcule a soma de todos os números ímpares dentro de uma faixa de valores determinada pelo usuário. Um numero é ímpar quando sua divisão por 2 não é exata, ou seja, o mod(%) resultante da divisão inteira do numero por 2 tem valor 1.Vejamos como fica o código: 7
if ((numero % 2)!= 0) <código para numero impar> else <código para numero par> Como o algoritmo solicita a soma dos valores ímpares dentro de uma faixa, teremos que fazer o acúmulo do resultado apenas quando a condição ímpar for atendida. Essa condição será testada para todos os números dentro da faixa, por meio de um laço. 8
#include <stdio.h> #include <stdlib.h> #include <locale.h> int main() { setlocale(lc_all,"portuguese"); unsigned short int n_inf, n_sup, s_impar; n_inf = n_sup = s_impar = 0; printf("informe 2 numeros referente ao intervalo: \n"); scanf("%d %d", &n_inf, &n_sup); 9
while (n_inf <= n_sup) { if ((n_inf % 2)!= 0) s_impar += n_inf; } n_inf++; } printf("soma dos Impares: %d\n", s_impar); return 0; 10
11
1. do o teste de mesa com intervalo definido entre 1 e 5. 2. Adapte o algoritmo Soma_Ímpares, para obrigar o usuário a entrar com um valor para o limite inferior menor que o valor definido para o limite superior. Para isto, faça um laço que garanta a entrada de um intervalo válido (inferior > superior). 12
Determinar if um numero é primo Faça um algoritmo que escaneie um numero inteiro positivo e determine if este é primo ou não. Por definição, um numero é primo quando é divisível somente por si próprio e por 1, Portanto, para determinar if um numero é primo, temos de definir por quais números é divisível. A aproximação mais simples, e que podemos dizer ser uma aproximação de 'força bruta', poderia ser testar a divisibilidade do numero avaliado por todos os números menores que ele, Vejamos a implementação deste algoritmo. 13
#include <stdio.h> #include <stdlib.h> #include <locale.h> #include <stdbool.h> int main() { setlocale(lc_all,"portuguese"); unsigned short int n1 = 0, divisor = 0; bool booleano = false; printf("informe o numero a ser testado: "); scanf("%d", &n1); 14
divisor = n1-1; while (divisor > 1 && booleano == false) { if (n1 % divisor == 0) booleano = true; else divisor = divisor - 1; } if (booleano == false) printf("número é primo!"); else printf("número não é primo!"); return 0; } 15
16
#include <stdio.h> #include <stdlib.h> #include <locale.h> int main() { setlocale(lc_all,"portuguese"); unsigned short int n1 = 0, divisor = 0; printf("informe o numero a ser testado: "); scanf("%d", &n1); 17
} divisor = n1-1; while (divisor > 1) { if (n1 % divisor == 0) { printf("número não é primo! \n"); exit(0); } else divisor -= 1; } printf("número é primo! \n"); return 0; 18
19
Apesar de o algoritmo Primo_Versão1 ser eficaz, visto que resolve o problema para o qual foi projetado, não if pode dizer que seja propriamente eficiente. Basta que analisemos com um pouco mais de profundidade que perceberemos que várias otimizações podem ser aplicadas ao raciocínio utilizado nesse algoritmo. Vejamos: 20
*Números pares (com exceção do 2) não podem ser primos, visto que são divisíveis por 2, if um numero não for divisível por 2, não será divisível por nenhum outro numero par. Portanto, com exceção do numero 2, só precisaremos testar números ímpares. **É mais fácil que um numero seja divisível por um numero pequeno do que por um numero maior, Portanto, if iniciarmos a procura do divisor de baixo para cima, ao invés de cima para baixo, como foi implementado, teremos chance de encontrar o numero muito antes. 21
***Nenhum numero pode ser divisível por outro numero maior que a metade dele. Portanto, não precisamos testar a divisibilidade dos numero na faixa entre a metade e o próprio numero. if levarmos em conta tais considerações, teremos um algoritmo muito mais eficiente que o anterior, pois executará muito menos instruções para responder a mesma questão. 22
LP1_16 23
LP1_16 24
Um raciocínio mais sofisticado pode ainda nos dar uma otimização final. Vejamos alguns exemplos para facilitar a compreensão deste ponto: 15 é divisível pelos números 1,3,5 e 15(1*15,3*5, 5*3 e 15*1). 16 é divisível pelos números 1, 2, 4, 8 e 16 (1*16,2*8,4*4,8*2 e 16*1). 17 é divisível pelos números 1 e 17(1*17 e 17*1). 20 é divisível pelos números 1, 2, 4, 5, 10 e 20 (1*20,2*10,4*5, 5*4,10 *2 e 20*1). 25 é divisível pelo números 1, 5 e 25 (1*25,5*5 e 25*1). 36 é divisível pelo números 1, 2, 3,4,6,9, 12, 18 e 36 (1*36, 2*18, 3* 12,4*9, 6*6,9*4, 12*3, 18*2 e 36*1). 25
Os exemplos anteriores são para ilustrar a seguinte propriedade da divisibilidade de um numero: qualquer numero que seja divisível por outro terá como divisores dois números ou fatores, e um será maior que o outro, a não ser que tais números sejam iguais (quando o numero tem uma raiz quadrada exata). No caso de divisores diferentes, o numero menor sempre será menor que a raiz quadrada do resultado da multiplicação e o numero maior, maior que a raiz quadrada do numero em questão. 26
Podemos perceber que quanto maior um dos fatores, menor o outro. A relação if inverte após a linha da raiz quadrada, quando os números if repetem em ordem inversa. Podemos, então, concluir que if um numero não for divisível por um numero menor ou igual à sua raiz quadrada, não terá outro divisor que não ele próprio ou o 1. ou seja, será um numero primo.****portanto, só precisamos testar a divisibilidade de um numero por valores iguais ou inferiores à sua raiz quadrada. Adaptando o algoritmo, teremos o que if vê no exemplo a seguir. 27
LP1_17 28
LP1_17 29
30