Dois algoritmos clássicos sobre números inteiros:
Vamos ainda ver a recursão: uma forma alternativa aos ciclos para especificar repetição.
Um número inteiro positivo \(n\) é primo se for divisível apenas por \(1\) e por \(n\):
2, 3, 5, 7, 11, 13 ...
Vamos especificar um algoritmo para testar se um número é primo.
Dado: \(n\) inteiro.
Se \(n\leq 1\) então não é primo e terminamos imediatamente.
Se \(n>1\) tentamos para \(d = 2, 3, \ldots, n-1\):
Se chegamos ao final sem encontrar um divisor: concluimos que \(n\) é primo.
#define FALSE 0
#define TRUE 1
/* Testar se um número inteiro é primo */
int primo(int n) {
int d;
if(n <= 1) return FALSE;
for (d = 2; d < n; d++) {
if (n%d == 0) // d divide n?
return FALSE;
}
return TRUE;
}
/* Testar se um número é primo;
versão mais eficiente */
int primo(int n)
{
int d;
if(n <= 1) return FALSE;
for (d = 2; d*d <= n; d++) {
if (n%d == 0) // d divide n
return FALSE;
}
return TRUE;
}
O máximo divisor comum (mdc) de dois inteiros \(a, b\) é o maior número inteiro que divide \(a\) e \(b\).
Exemplo:
\[ \begin{eqnarray} 252 &=& 21 \times 12 \\ 105 &=& 21 \times 5 \end{eqnarray} \]
Dados: \(a,\, b\) dois números inteiros positivos.
Calcular o mdc de 252 e 105.
iter | a | b |
---|---|---|
0 | 252 | 105 |
1 | 147 | 105 |
2 | 42 | 105 |
3 | 42 | 63 |
4 | 42 | 21 |
5 | 21 | 21 |
R: 21
/* Calcular o mdc de dois inteiros positivos
pelo Algoritmo de Euclides (1ª versão)
*/
int mdc(int a, int b)
{
while (a != b) {
if(a > b)
a = a - b;
else
b = b - a;
}
return a; // a, b são iguais
}
OK:
Questões:
Propriedade da divisão inteira:
Se \(d\) divide \(a\) e \(b\), então \(d\) divide \(a-b\) e \(d\) divide \(b-a\).
Em cada iteração:
\[ \begin{aligned} \text{se}~a>b: \quad & (a,b) \longrightarrow (a-b, b) \\ \text{se}~a<b: \quad & (a,b) \longrightarrow (a, b-a) \end{aligned} \]
(Versão usando resto da divisão.)
Dados: \(a,\, b\) dois inteiros não-negativos.
Calcular o mdc de 252 e 105.
iter | a | b | resto a ÷ b |
---|---|---|---|
0 | 252 | 105 | 42 |
1 | 105 | 42 | 21 |
2 | 42 | 21 | 0 |
3 | 21 | 0 |
R: 21
/* Calcular o mdc de dois inteiros usando
o algoritmo de Euclides (2ª versão)
*/
int mdc(int a, int b)
{
int r;
while(b != 0) {
r = a%b;
a = b;
b = r;
}
return a;
}
\[ \begin{eqnarray*} \text{fact}(0) &=& 1\\ \text{fact}(n) &=& n \times \text{fact}(n-1)\,, \quad \text{se}~n>0 \end{eqnarray*} \]
A definição anterior define um algoritmo: permite calcular o factorial de qualquer inteiro não negativo.
Exemplo:
\[ \begin{eqnarray*} \text{fact}(4) &=& 4 \times \text{fact}(3) \\ &=& 4 \times (3 \times \text{fact}(2))\\ &=& 4 \times (3 \times (2\times \text{fact}(1)))\\ &=& 4 \times (3 \times (2\times (1\times \text{fact}(0)))\\ &=& 4 \times (3 \times (2\times (1\times 1))) \\ &=& 24 \end{eqnarray*}\]
Podemos implementar este processo defindo a função recursiva em C:
int fact(int n)
{
if (n == 0)
return 1; // caso base
else
return n * fact(n-1); // caso recursivo
}
Há dois casos na definição anterior:
o factorial de zero é 1 (sem mais chamadas recursivas)
calculamos o factorial do natural anterior e multiplicamos o resultado por \(n\)
Para que uma definição recursiva termine é suficiente que:
Exemplo: na função de fact
n == 0
n-1
n
)Logo: fact
termina para qualquer n
maior ou igual a 0.
int fact(int n) {
int r = 1; // resultado
for(int i = 1; i<=n; i++)
r = r*i;
return r;
}