Você está na página 1de 5

Matemtica Discreta

Recurso
Marco Antnio Queiroz
25 de maio de 2012
TADS Tecnologia em Analise e Desenvolvimento de Sistema
rea de Cincias Exatas e Tecnologia Instituto Federal Goiano Campus Uruta
Rodovia Geraldo Silva Nascimento Km 2,5. CEP 75790-000-Brasil
marco.aq@live.com
Resumo
Seguindo o trabalho proposto, utilizando recurso em algortimos para calculo do fatorial de dez mil, os mil primeiros
valores de fibonacci e a torre de hanoi com quarenta pinos que foi aplicado no desenvolvido, obteve-se alguns
resultados e que sero discutidos a seguir.
Introduo
Recurso uma das tcnicas mais simples e teis que existem para usarmos em nossos algoritmos que consiste em uma
funo chamar a si mesmo, at que o retorno seja trivial.

Fibonacci
A Sequncia de Fibonacci consiste em uma sucesso de nmeros, tais que, definindo os dois
primeiros nmeros da sequncia como 0 e 1, os nmeros seguintes sero obtidos por meio da soma
dos seus dois antecessores. Portanto, os nmeros so: 0,1,1,2,3,5,8,13,21,34,55,89,144,233,...
Dessa sequncia, extrai-se o nmero transcendental conhecido como nmero de ouro.
A sequncia de Fibonacci dada pela frmula:

Uma das aplicaes da sequnciade Fibonacci a identidade de Cassini.

Hani
A Torre de Hani um "quebra-cabea" que consiste em uma base contendo trs pinos, em um dos
quais so dispostos alguns discos uns sobre os outros, em ordem crescente de dimetro, de cima
para baixo. O problema consiste em passar todos os discos de um pino para outro qualquer, usando
um dos pinos como auxiliar, de maneira que um disco maior nunca fique em cima de outro menor
em nenhuma situao. O nmero de discos pode variar sendo que o mais simples contm apenas
trs.
Para entender a lgica da Torre de Hani necessrio analisar a construo de diferentes nveis da
torre com o nmero mnimo de movimentos, tendo o nvel anterior j formado, sendo que esses
nveis so o nmero de peas desintegradas da torre original que iro formar outra torre com os
menores discos.
Para mover o primeiro disco da torre original, 1 movimento gasto. Para mover o segundo da torre
original, sendo que o primeiro j foi movido e ser construda uma torre com os 2 menores discos,
so gastos 2 movimentos. Para deslocar o terceiro disco formando nova torre com os trs menores
discos, tendo a torre com os dois menores j formada, so gastos 4 movimentos.
Assim se sucede com os prximos discos at que o ensimo disco (o ltimo) seja deslocado
compondo uma torre com os outros discos tendo uma torre com o penltimo disco e os demais
juntos j formada. A sucesso formada pela soma dos movimentos uma sucesso.
temos

Fatorial
O fatorial de um nmero n (n pertence ao conjunto dos nmeros naturais) sempre o produto de
todos os seus antecessores, incluindo si prprio e excluindo o zero. A representao feita pelo
nmero fatorial seguido do sinal de exclamao, n! . Exemplo de nmero fatorial:
6! = 6 . 5 . 4 . 3 . 2 . 1 = 720

Alguns problemas recursivos


H um pequeno preo a pagar pela beleza: espao em memria.
Na verso no-recursiva, ele far o clculo de T(10) (o valor da soma de zero a dez) assim:
soma comea de 0; para i de 0 ate n, some i ao valor da soma e jogue em soma(sobrescrever).
Assim, ocorre algo assim nas posies de memria:
soma 0 1 3 6 10 15 21 28 36 45 55
i
0 1 2 3 4 5 6 7 8 9 10
Rpido, fcil e simples.
Agora a verso recursiva. Nela, os valores desconhecidos so colocados numa pilha na memria.

T(10)=T(9)+10 >| T(9)=T(8)+9 >| T(8)=T(7)+8 >| T(7)=T(6)+7 >| T(6)=T(5)+6 >| T(5)=T(4)+5 >|
T(4)=T(3)+4 >| T(3)=T(2)+3 >| T(2)=T(1)+2 >| T(1)=T(0)+1=1
At agora cada valor foi colocado numa pilha, com a ordenao inversa do modo que eu ilustrei.
Assim, agora a mquina ir retornar os valores, um a um:
T(2)=3 | T(3)=6 | T(4)=10 | T(5)=15 | T(6)=21 | T(7)=28 | T(8)=36 | T(9)=45 | T(10)=55
Limitado por sua memria
Dado o problema anterior e dando continuidade, temos tambm a limitao do uso de nmeros de
qualquer tamanho, limitado apenas a sua memria. Quando se fala em nmeros, deve-se remeter
para o tamanho da palavra que a ULA suporta (Unidade Lgica e Aritmtica). Assim, em 32 bits, o
maior inteiro que o processador consegue lidar 4.294.967.295 e isto apenas se for considerado
nmeros inteiros positivos, sem sinal. Como os processadores utilizam a representao
complemento de dois para nmeros inteiros, ao permitir que se use sinal a faixa de representao de
um inteiro em 32 bits vai de -2.147.483.648 at +2.147.483.647 (com complemento de dois ganhae uma representao a mais no lado negativo).
O mais interessante que em uma arquitetura de 32 bits, apenas o fatorial de 12 pode ser calculado.
Se for tentar calcular o fatorial de 13, este daria 6.227.020.800, nmero que no pode ser
representado em 32 bits. Agora se voc possui um processador de 64 bits, um sistema operacional
de 64 bits e compilar o cdigo em C o usando um gcc para 64 bits, voc um felizardo pois o
programa conseguir calcular o fatorial de 22, pois fatorial de 23 resulta em
25.852.016.738.884.976.640.000 e este valor no cabe em 64 bits. Isto, ainda, considerando o uso
dos inteiros sem sinal.
Um erro que comete foi pensar que trocando a varivel para double, meus alguns dos meus
problemas seria resolvidos, porem aps o trabalho entendi que double apenas um inteiro
maior(preciso).
No entanto j existem diversas solues em vrias linguagens que permitem manipular nmeros
inteiros de qualquer tamanho.
Dividir para conquistar
A ULA no suportar informaes maiores do que 32 bits (ou 64), no significa que no se pode ir
alm disto. Significa apenas que ela mesmo, a ULA, no consegue lidar com um nmero maior do
que isto de uma nica vez.
Para explicar o conceito, que tal pensarmos em qual o tamanho da nossa ULA?
Voc consegue, com a "sua ULA", executar esta operao 059 + 064?
Se voc respondeu que SIM, desculpe, mas voc errou.
Tipicamente "nossa ULA" de apenas um decimal. S conseguimos lidar com um dgito de cada
vez. Quero dizer que desde a primeira srie aprendemos a usar o conceito de dividir para conquistar.
provvel que voc, para executar a soma anterior, usou a velha tcnica da primeira srie:
059
+ 0 6 4 primeira etapa: 9 + 4 = 13
----3 (e vai um)
1
059
+ 0 6 4 segunda etapa: 5 + 6 + 1(que veio) = 12
----2 3 (e vai 1)

11
059
+ 0 6 4 terceira etapa: 0 + 0 + 1(que veio)
----1 2 3 (FIM)

Sua ULA de apenas um dgito! Voc precisou decompor as operaes complexas em vrias
menores para conseguir resolver.
O mesmo conceito se aplica para qualquer processador. possvel, atravs de programao, fazer
uma operao complexa dividindo ela em operaes menores, cada uma suportada pela ULA.
Assim como o Java, o C no possui suporte a nmeros gigantes em sua sintaxe. Se fosse C++ a
soluo seria semelhante ao Java, ou seja, atravs do uso de alguma classe que manipule estes
inteiros. Mas no C tudo funo e uma biblioteca precisa ser usada para isto.
Uma das mais fantsticas bibliotecas que a OpenSSL. Ela tem tudo o que diz respeito a
criptografia.
Como muitos algoritmos de criptografia necessitam manipular inteiros alm da capacidade da ULA,
a biblioteca OpenSSL implementou suporte a nmeros gigantes internamente. Usar apenas a parte
de nmeros big pode ser feito inserindo-se a biblioteca bn.h do OpenSSL.
Assim como no Java, que tambm no tem suporte a estes nmeros em sua sintaxe, toda a
manipulao destes nmeros deve ser feita usando-se funes apropriadas, como no exemplo
comentado do cdigo que calcula o fatorial.
#include <stdio.h>
#include <openssl/bn.h>
int main(int argc, char *argv[]){
BIGNUM *fat; // declarao de uma varivel Big
BN_ULONG a, f; // apenas um long int normal
char *resp;
int i;
/* Primeiro tem que alocar as variveis BIGNUM */
fat = BN_new();
for (i = 1; i < argc; i++) {
printf("Calculando fatorial de %s\n", argv[i]);
/* convertendo string em long int */
f = atoll(argv[i]);
/* forma de atribuir 1 a uma varivel BIGNUM */
BN_dec2bn(&fat, "1");
for (a = 2; a <= f; a++) {
BN_mul_word(fat, a);
}
/* gerando uma string imprimvel do resultado */
resp = BN_bn2dec(fat);
/* impresso do resultado (agora uma string) */
printf("Fatorial de %s = %s\n", argv[i], resp);
}
}

Para poder compilar o programa em C anterior necessrio ter instalado as bibliotecas OpenSSL
para desenvolvimento. No caso do Ubuntu deve-se instalar o pacote ssl-devel (e, evidentemente, ter
instalado todos os pacotes de desenvolvimento bsico pois o Ubuntu vem at sem gcc!). Na

compilao necessrio ligar com a lib ssl:


$ gcc fatorialBIG.c -lssl -o fatorialBIG
Esta biblioteca, assim como o Java, possui funes para realizar as operaes, seja de comparao,
atribuies, converso de e para string. Particularmente as operaes aritmticas so extremamente
completas para dar suporte aos algoritmos de criptografia.
Resultados
No desenvolvimento do trabalho houve a necessidade de se guardar valores na memria feito
atravs de variveis, no entanto o principal problema enfrentado foi o estouro. Em C, para utilizar
uma varivel, ela deve ser primeiramente declarada, ou seja, devemos requisitar o espao necessrio
para essa varivel, e com a utilizao de bibliotecas OpenSSL para o desenvolvimento, foi possvel
declarar variveis do tipo BIGNUM, tornando possvel o calculo de nmeros gigantes, assim como
foi dado como problema para calculo de fatorial superiores 13.
Para a concluso do trabalho, achei interessante o comentrio do Teixeira em 15/08/2009 na artigo
do Elgio / vivaolinux, que diz:
...Muito embora no passemos toda a nossa vida calculando fatoriais, certos conhecimentos so
muito importantes, tornando-se isso por vezes o fio de alguma meada ou o prprio caminho das
pedras, ajudando-nos a resolver outros tipos de problemas...
o conhecimento que diverte, ou a diverso que educa: No importa a definio.
E tem gente que faz muito mais que simplesmente escovar bits:
Trabalhei em uma indstria onde o controle de estoque somente era possvel atravs de uma tcnica
(em linguagem de mquina) que dividia cada byte ao meio, e cada metade controlava um produto
diferente.
Observe-se que para isso uma das metades ( a que contm o registrador SO ) que tinha de ser
"enganada" e usada integralmente para armazenar dados...
J no me lembro como se faz isso, mas a coisa era por a.
Detalhe: A memria total era limitada a 512 bytes.
No fui eu quem implementou esse sistema, mas algum o fez, a partir de alguma idia e
certamente de bastante transpirao. Criatividade, conhecimento e dedicao. Muita dedicao.
Ento, conclui-se que algumas coisas que podem eventualmente parecer "inteis" , "suprfluas" ou
"doideira" (como calcular fatorial, raiz quadrada, dividir bytes ao meio, etc.) podero ter o seu dia
de "Eureka!!!!" bem mais cedo do que se imagina.
A propsito de Python:
Existe um software homnimo (um personal messenger) cujo logo o de uma serpente de aspecto
terrvel, com enormes presas inoculadoras de veneno.
As pitons no entanto, assim como as jiboias e as anacondas so constritoras e no possuem presas
nem veneno.
No entanto, o nome da linguagem Python no vem da serpente, sendo apenas uma aluso ao
conjunto Mounty Python...
Desculpe o pythaco...
Apos o comentrio espirador do Teixeira, fica ento por acabado essa parte do trabalho.
Bons estudos!
Fontes:
pt.wikibooks.org/wiki/Programar_em_C/Vari%C3%A1veis
vivaolinux.com.br/artigo/Mais-sobre-recursividade-em-C-C++
vivaolinux.com.br/artigo/Programacao-com-numeros-inteiros-gigantes?pagina=5
pt.wikibooks.org/wiki/De_Objective_Caml_para_C_e_C%2B%2B/Constru
%C3%A7%C3%A3o_de_tipos