Académique Documents
Professionnel Documents
Culture Documents
Programao de Computadores
usando Logisim e Scilab
Osvaldo Carvalho
Departamento de Cincia da Computao
UFMG
osvaldo@dcc.ufmg.br
1 Semestre de 2011
IOPC 2011_1-4.docx
2
Contedo
1 Introduo ........................................................................................................................ 1
1.1 Computadores ........................................................................................................... 1
1.2 Informao Analgica e Informao Digital ................................................................ 5
1.3 Computadores e Informao ..................................................................................... 7
1.4 Converses anlogo-digital e digital-analgica ........................................................... 9
1.5 Sensores e atuadores............................................................................................... 13
1.6 Memrias ................................................................................................................ 15
1.7 Organizao do Texto .............................................................................................. 18
1.7.1 Organizao de Computadores ........................................................................ 18
1.7.2 Linguagem e Ambiente Scilab........................................................................... 20
1.7.3 Algoritmos e Programas ................................................................................... 22
2 Organizao de Computadores........................................................................................ 25
2.1 Bits e cdigos........................................................................................................... 25
2.2 Circuitos Combinatrios........................................................................................... 28
2.2.1 lgebra de Boole.............................................................................................. 29
2.2.2 Portas Lgicas .................................................................................................. 29
2.2.3 Introduo ao Logisim ...................................................................................... 33
2.2.4 Aritmtica com operaes lgicas .................................................................... 38
2.2.5 Sntese de Circuitos Combinatrios .................................................................. 44
2.2.6 Comparao de binrios sem sinal ................................................................... 50
2.2.7 Multiplexadores e Demultiplexadores .............................................................. 53
2.3 Circuitos Sequenciais ............................................................................................... 56
2.3.1 Flip-flops e Registradores ................................................................................. 56
2.3.2 Barramentos e Controle de Fluxo de Dados ...................................................... 59
2.3.3 Memrias ........................................................................................................ 60
2.3.4 Acumuladores .................................................................................................. 62
2.4 Processadores ......................................................................................................... 63
2.4.1 Uma Calculadora.............................................................................................. 63
2.4.2 Osciladores ou Clocks....................................................................................... 65
2.4.3 Micro-instrues .............................................................................................. 66
2.4.4 Desvios ............................................................................................................ 74
2.4.5 Desvios condicionais ........................................................................................ 77
2.4.6 Instrues e Programao em Assembler ......................................................... 79
Aos Professores
Programao de Computadores a disciplina mais tradicionalmente oferecida por
departamentos de Cincia da Computao, e geralmente tambm a de maior nmero de
matrculas. Na UFMG, Programao de Computadores j era oferecida para Cincias e
Engenharias alguns anos antes da criao do departamento. Seu cdigo DCC001, o que d
uma idia de sua venerabilidade. Este texto parte integrante de um conjunto de materiais
pedaggicos para esta disciplina, produzidos com a inteno de serem usados em um curso de
60 horas-aula, dado em um semestre letivo. Exerccios, imprescindveis para um bom
aprendizado, no esto aqui, mas em um site Moodle que contm tambm apresentaes,
vdeos e outros materiais.
O enfoque adotado apresenta algumas caractersticas que o distinguem da forma tradicional
como a a disciplina ministrada:
O curso necessita de um professor e de monitores;
Em cada semana so previstas uma aula expositiva, dada pelo professor, e uma aula
prtica, dada pelos monitores;
Aulas expositivas podem ser dadas em auditrio ou sala de aula com grande
capacidade;
Aulas prticas so oferecidas em laboratrios com computadores; melhores resultados
podem ser esperados com turmas pequenas;
Os procedimentos de avaliao do aluno incluem questionrios semanais e provas,
que podem (e devem) ser realizados online;
As aulas prticas tm como objetivo auxiliar os alunos nas avaliaes semanais;
Uma base de questes, fechadas e abertas, est disponvel no Moodle para a
montagem de avaliaes.
Questes fechadas (mltipla escolha, associaes, etc.) so corrigidas
automaticamente; ao montar uma avaliao, o professor deve dosar o uso de
questes abertas para manter o trabalho de correo em volumes aceitveis.
Conjuntos de exerccios podem tambm ser disponibilizados no Moodle, permitindo
estudos e auto-avaliaes pelos alunos;
A linguagem adotada o Scilab;
O primeiro tero do curso dedicado ao ensino de circuitos lgicos e organizao de
computadores, utilizando o software Logisim (1) (Burch, 2002);
Mesmo com um enfoque eminentemente prtico, o material cobre conceitos tericos
fundamentais, como complexidade de algoritmos, problemas np-completos e
problemas indecidveis.
Com relao ao contedo, os dois pontos que provavelmente necessitam de maiores
justificativas so o estudo de organizao de computadores e a adoo de Scilab. A nosso ver o
estudo de organizao de computadores abre oportunidades para a introduo de diversos
conceitos fundamentais para a programao de computadores. O aluno tem contato com bits,
com operaes lgicas, com cdigos importantes como ASCII e ponto flutuante. Acumuladores
so o primeiro contato com loops, e somadores so um excelente exemplo de modularizao.
A execuo seqencial de instrues e instrues de desvios so tambm elementos para a
formao na mente do aluno de um mecanismo de execuo de programas. E, talvez mais
importante, o primeiro contato com a programao se d sem a necessidade de abstraes
com relao executabilidade dos programas.
Para justificar a adoo do Scilab preciso falar um pouco sobre o fenmeno MatLab. MatLab,
de Matrix Laboratory, uma linguagem chamada M e um ambiente de desenvolvimento e
execuo voltado para aplicaes tcnicas. Segundo Bill McKeeman (um dos pioneiros do
Computer Science Department de Stanford, hoje professor de Dartmouth e desenvolvedor da
MathWorks (2), empresa que vende e mantm o MatLab), a linguagem teve origem na idia de
colocar clculos matriciais na sintaxe, ao invs de utilizar chamadas de subrotinas em Fortran
(3).
Com poucas mas muito bem sucedidas excees, MatLab no conhecido em departamentos
de Cincia da Computao. No s aqui no Brasil que isto acontece. MatLab no foi
projetado por especialistas em linguagens ou compiladores, no tendo aos olhos de cientistas
da computao (incluindo este autor) qualquer importncia conceitual como linguagem de
programao. Mas seu sucesso prtico sem qualquer dvida enorme. Ao apresentar a
linguagem M para o MIT em 2005, McKeeman inicia dizendo as it turns out, the computer
science department is about the only part of MIT that does not use MatLab. Ele continua
(McKeeman):
MATLAB has grown over 20 years from academic research into a generalized tool for a
wide variety of applications, including vehicle crash simulation, financial prediction,
genome analysis, imbedded computer control, aircraft design and so on. More than 200
MathWorks developers are working on the next release. Another 1000 people run the rest
of the business, in Natick and worldwide.
There are about a million users. Some MATLAB users do not think of what they are doing as
"programming." Some users are interested in quick and easy results. Some users want to
build applications that are bullet proof and reusable over decades. I know of 100000 line
MATLAB programs and MATLAB programs mining petabytes of data and others running
100x parallel for days at a time. Some universities teach MATLAB for beginning
programming. On every customer contact I find new surprises. MATLAB satisfies all these
communities.
O Scilab um sistema livre, produzido pelo INRIA, que segue a mesma filosofia do MatLab,
mas sem tentar ser um clone. A compatibilidade das linguagens de programao grande mas
no total. Segundo o verbete na Wikipedia, SciLab vem conquistando cada vez mais adeptos
tanto na academia como na indstria. Existem livros sobre SciLab em ingls, francs e
espanhol, e est disponvel na Internet um texto introdutrio em portugus produzido pelo
Prof. Paulo Srgio da Mota Pires, da UFRN (4). Links para esses materiais podem ser
encontrados no site (5) (Scilab Consortium).
Quanto s avaliaes freqentes, a sua contribuio para a experincia de aprendizado
consensual. Dentre as principais caractersticas de cursos altamente respeitados, levantadas
pelo projeto Harvard Asssesssment Seminars (6), esto:
1. Immediate and detailed feedback on both written and oral work.
2. High demands and standards placed upon [students], but with plentiful opportunities
to revise and improve their work before it receives a grade, thereby learning from their
mistakes in the process.
3. Frequent checkpoints such as quizzes, tests, brief papers, or oral exams. The key idea is
that most students feel they learn best when they receive frequent evaluations,
combined with the opportunity to revise their work and improve it over time.
Entretanto, avaliaes exigem correes e, com a atual presso por produtividade medida pela
relao alunos/professor, o trabalho de correo pode se tornar inaceitvel. preciso
equilibrar o uso de questes fechadas, corrigidas automaticamente, com o de questes
abertas, imprescindveis em um curso de programao de computadores mas que exigem
correo manual. Mesmo controlando o uso de questes fechadas, o auxlio dado por uma
equipe de monitores pode ser essencial para se manter avaliaes semanais.
Agradecimentos
A metodologia adotada para Programao de Computadores (uma aula expositiva e uma aula
prtica por semana) e a nova linguagem (Scilab) nos foram sugeridas pelos Professores Regina
Helena Bastos Cabral e Ivan Moura Campos. Os dois me fizeram conhecer o Matlab, me
convenceram da necessidade de prticas mais intensivas, e tambm da viabilidade de provas
online. A Professora Regina j aplicava estas tcnicas com enorme sucesso em Clculo
Numrico.
Os monitores que trabalharam na disciplina em sua primeira oferta em 2007 foram Maxstaley
Neves e Henrique Chevreux. Sem eles eu no teria conseguido enfrentar a mirade de detalhes
tcnicos do Logisim, Moodle e Scilab, todos ento sistemas novos para mim. Mas, muito mais
do que isso, eles forjaram para a monitoria uma postura ntegra, competente e criativa,
postura que souberam transmitir aos outros monitores: Harlley Augusto de Lima, Phillippe
Samer Lallo Dias, Rafael Bonutti, Douglas Max Duarte Batista, Luis Cludio Dutra Martins,
Rafael Vieira Carvalho e Thiago Moreira Torres.
A aplicao da metodologia faz uso intenso da infra-estrutura de tecnologia da informao da
UFMG, competentemente administrada pelo Centro de Computao, pelo Laboratrio de
Computao Cientfica, pelo Laboratrio de Recursos Computacionais do Instituto de Cincias
Exatas e pelo Centro de Recursos Computacionais do Departamento de Cincia da
Computao.
1 Introduo
1.1 Computadores
Este um texto sobre organizao e programao de computadores. Apenas meio sculo aps
a construo dos primeiros computadores, o impacto desta tecnologia sobre nossas vidas
enorme. Computadores mudaram e muito a forma como se faz msica, cinema ou artes
plsticas, como se escrevem textos, como se faz comrcio. A medicina mudou, e mudaram a
engenharia, as cincias, a economia. Mudaram as formas de governar, e as formas de exerccio
de cidadania. Mas o que um computador?
Vamos comear com alguns exemplos. certo que voc j viu diversos computadores, e
provvel que a imagem que lhe venha mente seja similar mostrada na Figura 1.
Este o primeiro computador pessoal lanado pela IBM. Apesar de ser precedido por diversos
outros micro-computadores, o IBM PC foi um marco a IBM era ento a empresa dominante
na indstria da computao, capaz de lanar padres.
Existem computadores que no se assemelham a PCs. Alis, os computadores existentes em
maior nmero so simples e pequenos, embutidos em telefones celulares, iPods,
eletrodomsticos e automveis. Outos so enormes, ocupando vastos sales, como o Blue
Gene mostrado na Figura 2. Em 2006 o Blue Gene era o computador mais poderoso do mundo,
sendo capaz de executar 478 trilhes de operaes aritmticas por segundo. Em 2008 j no
era: o RoadRunner, que como o Blue Gene foi produzido pela IBM, atingiu 1 petaflops, isto ,
mil trilhes de operaes aritmticas por segundo. Como curiosidade, o RoadRunner utiliza
chips (circuitos integrados) usados na PlayStation 3 da Sony.
A cada seis meses uma lista com os maiores computadores do mundo publicada no site da
organizao Top500 (8). Na lista de novembro de 2010, pela primeira vez o computador mais
possante no era produzido nos Estados Unidos. Sinal dos tempos, o primeiro lugar da lista foi
ocupado chins Tianhe-1A, com um desempenho de 2,6 petaflops. Vale a pena visitar este
site, que contm dados e anlises interessantes sobre a evoluo dos supercomputadores,
denominao que a indstria d a computadores como o Blue Gene, RoadRunner ou Tianhe-
1A.
Com a rpida evoluo da eletrnica, poderoso hoje, normal amanh, fraco depois de amanh.
Para ter alguma utilidade o termo forosamente relativo poca: um supercomputador
um computador que figura dentre os mais poderosos do mundo ... em sua gerao.
Neste sentido o Mark I (Figura 3), de 1944, executando apenas 3 operaes aritmticas por
segundo, era mais super que o Blue Gene ou que o Tianhe-1A, pois era um dos nicos
computadores existentes no mundo. Seus concorrentes eram mquinas de calcular mecnicas.
Olhando para a imagem (Figura 6) de um chip do processador Intel Core i7-980X, lanado em
2010, ns podemos perceber diversos sub-mdulos. Se pudssemos olhar ainda mais de perto,
veramos que este chip contm 1,17 bilhes de transistores, espremidos em uma rea de
apenas 248 milmetros quadrados.
Fazendo agora um zoom na direo contrria, temos a Internet, a rede mundial que conecta
praticamente todos os computadores do mundo. A imagem da Figura 7 propositalmente
lembra uma galxia. So milhes de computadores na Internet, todos interligados.
Figura 7: Uma visualizao da Internet pelo produzida pelo Projeto Opte (14). Em azul esto os ns da Amrica do
Norte, em verde os da Europa, Oriente Mdio, sia Central e frica, e em amarelo os da Amrica Latina.
Todo esse arranjo envolvendo satlites de telecomunicaes, cabos submarinos, redes com e
sem fios, fibras ticas, computadores, telefones celulares, circuitos integrados, incrivelmente,
tudo isso funciona, com algumas falhas, verdade, mas que de forma alguma impediram a
computao de mudar a forma de vida da humanidade. Funciona como? Essa proeza de
organizao se deve exatamente ao uso intenso, onipresente, de uma idia central para a
computao, a modularizao. So muitas e muitas peas, mas que so desenvolvidas
conforme padres que permitem que, para utilizar um mdulo, seja preciso saber apenas o
que esse mdulo faz, e no como ele construdo.
Um filme fotogrfico revelado objeto em extino nos dias de hoje registra informao
sobre a cena fotografada. Um arquivo JPEG, formato comum para imagens digitais, tambm
tem. Uma mesma cena, fotografada com uma mquina tradicional, gera informao analgica
sobre o material foto-sensvel que cobre o filme; fotografada com uma mquina digital, gera
smbolos, ou seja, informao digital.
Ponto de ebulio
da gua
Corpo humano
Ponto de fuso
do gelo
Com o uso de uma escala, um mdico pode anotar em um papel a temperatura de seu
paciente. Ao faz-lo, a informao sobre a temperatura passa de analgica (a altura da coluna
de mercrio) para informao digital ou simblica (o nmero anotado pelo mdico).
Ponto de ebulio
da gua
Corpo humano
Ponto de fuso
do gelo
Ponto de ebulio
da gua
50
Corpo humano
50
Ponto de fuso
do gelo
Smbolos podem tambm ser usados para representar outros smbolos. Assim como explicitar
uma escala um requisito para se interpretar um nmero associado a uma temperatura, a
correspondncia entre smbolos deve ser estabelecida por convenes, como mostra o
exemplo na Tabela 1.
Podemos ver que o uso de apenas 2 smbolos no traz limitao alguma de representatividade.
Tudo bem, mas porque s 2 smbolos? Se os computadores fossem menos mesquinhos e
usassem, por exemplo, os algarismos decimais como unidade bsica de informao, no
teramos um sistema que, antes de qualquer coisa, seria familiar, e que com algarismos
poderamos representar coisas diferentes?
A deciso de adoo de um sistema binrio foi tomada pelos projetistas dos primeiros
computadores, e se justifica principalmente pela confiabilidade. Computadores so
equipamentos eletrnicos, onde smbolos devem ser representados por voltagens ou
Para digitalizar um sinal de entrada como o da Figura 14 preciso obter amostras de sua
amplitude em instantes discretos no tempo, e digitalizar obter um valor numrico cada
amostra.
Figura 15: Sinal original e sinal amostrado nos instantes correspondentes aos traos verticais em vermelho,
usando 8 bits e frequncia de amostragem de 41,67 MHz
A Figura 15 ilustra esse processo de digitalizao. Se reconstituirmos este sinal a partir dos
valores das amostras, mantendo constante o valor do sinal nos intervalos de tempo entre duas
amostras, iremos obter o sinal direita na figura. Sem dvida, o sinal reconstitudo se
assemelha ao sinal original, mas as perdas decorrentes da digitalizao so evidentes.
Figura 16: Digitalizao com frequncia de amostragem insuficiente, produzindo um sinal completamente
distorcido. Sinal amostrado com 8 bits e frequncia da amostragem 6,17 MHz
Figura 17: A qualidade da digitalizao melhora com a frequncia de amostragem. Sinal amostrado com 8 bits e
frequncia de amostragem de 200 MHz
Na Figura 17 vemos o mesmo sinal sendo digitalizado com uma freqncia de amostragem
bem maior. O sinal amostrado j est bem prximo do sinal original. Podemos sempre tentar
aumentar a freqncia de amostragem, mas isso tem custos. Se considerarmos que o sinal
est sendo amostrado para apreciao visual por humanos, a partir de um certo ponto a
qualidade da digitalizao atingir os nossos limites de acuidade visual.
Figura 18: Sinal amostrado com f = 200 MHz, mas com apenas 2 bits de resoluo
Como dissemos, a preciso com que a amplitude do sinal em cada amostra digitalizada
tambm influi na qualidade da converso. Na Figura 18 ns vemos o efeito do uso de apenas
dois bits para a digitalizao da amplitude em cada amostra, e na Figura 19 a digitalizao com
um nico bit.
Figura 19: Sinal amostrado com f = 200 MHz, com um nico bit de preciso
As ilustraes da Figura 14 Figura 19 foram obtidas com o software ADconversion, que voc
pode obter no site(15). Faa o download, brinque com os parmetros da digitalizao
(freqncia de amostragem e bits de preciso), e veja os resultados.
importante observar que a converso em qualquer dos dois sentidos nunca perfeita, mas
em muitos casos pode ser to boa quanto se necessita. Em converses D/A (Digital/Analgica)
destinadas absoro por humanos, a explorao de limites fisiolgicos como a acuidade
visual ou auditiva muito utilizada.
A informao digital recebida pelo computador por sensores (ou equipamentos de entrada)
e, normalmente aps alguma transformao, enviada para atuadores (ou equipamentos de
sada).
Outras pessoas, pelo contrrio, tm grande facilidade para a digitao. O recorde mundial de
digitao pertence a Barbara Blackburn, que atingia uma velocidade sustentada de 15 toques
por segundo, com picos de 20 toques por segundo, usando um teclado Dvorak. Estamos nos
permitindo essa digresso para calcular a velocidade de produo de informao por um
teclado. Considerando que cada toque produz um byte ou 8 bits, a Barbara Blackburn produzia
informao a uma taxa de 160 bps (bps = bits por segundo).
A cincia faz uso de sensores que produzem informao muito mais rapidamente. Rdio-
telescpios ou aceleradores de partculas podem produzir informao taxas de 1Gbps, ou
seja, um bilho de bits por segundo, quase 7 milhes de vezes mais rpido do que o recorde
mundial de digitao.
1.6 Memrias
Memrias so usadas por computadores para registrar informaes para recuperao
posterior. Um computador geralmente trabalha com diversos tipos de memria, que seguem
uma distribuio hierrquica:
Registradores so memrias muito pequenas e muito rpidas, que se encontram
dentro do mesmo chip do processador, e que tm suas entradas e sadas ligadas
diretamente a circuitos que realizam transformaes de informao, como a unidade
aritmtica que, como o nome indica, realiza operaes aritmticas.
Memria principal ou RAM (Random Access Memory) um circuito externo ao
processador, mas de acesso ainda bastante rpido. Instrues executadas pelo
processador utilizam diretamente operandos armazenados na memria principal.
Transformaes como operaes aritmticas geralmente exigem que informao seja
previamente transferida da memria principal para registradores, onde as operaes
so realizadas, e os resultados posteriormente armazenados na memria principal. De
uma forma geral a memria principal voltil, no sentido em que necessrio manter
o computador ligado para que a informao ali armazenada no se perca. A
volatilidade no uma necessidade, mas uma caracterstica da tecnologia empregada
nas memrias principais atuais. H alguns anos atrs memrias principais utilizavam
Figura 28: Memria de ncleos de ferrite, usada em 1964 pelo supercomputador CDC 6600, com 64 palavras de
64 bits em 11x11 cm (16)
Figura 29: Um disco rgido sem a cobertura protetora, mostrando o movimento da cabea de leitura e gravao
Figura 30: Armazenamento tercirio com uma grande coleo de fitas magnticas manipuladas por um brao
mecnico de um rob
Figura 31: Circuito combinatrio, simulado no Logisim, que realiza a soma de duas parcelas binrias de 4 bits
Circuitos seqenciais tm a sua sada influenciada tambm pelo valor corrente de suas
memrias. O elemento bsico de memria o flip-flop, capaz de armazenar um bit. Conjuntos
de flip-flops formam registradores, que so ligados a outros registradores e a circuitos
combinatrios por meio de barramentos. So tambm introduzidos circuitos de memrias
onde ficam armazenados dados e programas. Osciladores e registradores circulares so
introduzidos como elementos para controle da evoluo temporal de um circuito.
Figura 32: Circuito sequencial, simulado no Logisim, que acumula a soma das entradas.
A primeira parte culmina com a apresentao de processadores simples, que so circuitos que
transformam informao de forma flexvel, determinada por um programa que carregado
em uma memria, e que pode ser substitudo com facilidade.
Cada linha do arquivo contm uma medida do nvel do mar; a aparelhagem do laboratrio
permite fazer 30 medidas por segundo. O arquivo completo tem 4096 linhas. Ns queremos
um programa para obter um grfico com os pontos do arquivo, e tambm saber os valores
mximo e mnimo presentes na amostra.
Funes utilizadas
// Programa da Onda
getf("Minimo.sci"); Leitura do arquivo
getf("Maximo.sci");
arq = xgetfile(); Gerao do grfico
Onda = fscanfMat(arq);
Sada
plot2d(Onda);
printf("Min = %5.2f, Max = %5.2f",...
Minimo(Onda), Maximo(Onda));
Figura 34: O programa Scilab Onda.sci. Cada linha um comando, a no ser que termine em .... Linhas que se
iniciam com // so comentrios que se destinam a leitores humanos.
A Figura 34 mostra um programa Scilab que faz isso, utilizando dois mdulos, as funes
Maximo e Minimo, mostradas na Figura 35.
Para entender melhor essas funes, veja o algoritmo descrito na Seo 1.7.3. O programa
produz o grfico da Figura 36, e a sada Min = -0.86, Max = 0.36 mostrada na
console do Scilab.
Como um exemplo, queremos encontrar o menor valor presente em uma coleo de nmeros.
Com 10 nmeros, como mostrados na Figura 37, fcil; podemos faz-lo por inspeo visual.
Mas como encontrar o menor valor entre, digamos, 50.000 nmeros? Para isso precisamos de
um algoritmo, isto , de um mtodo que tenha como informao de entrada a coleo de
nmeros, e como sada o menor valor ali presente.
Em programao uma coleo de nmeros chamada vetor. O primeiro elemento de um vetor
notado ; o quinto, ; o -simo, . Queremos portanto construir um algoritmo
que encontre o menor valor em um vetor de tamanho arbitrrio. Para isso, vamos comear
com o caso mais simples possvel: um vetor com um nico elemento, que obviamente o
menor elemento presente no vetor. Tudo bem, mas queremos trabalhar com vetores grandes
de verdade.
Para avanar, usamos induo. Suponhamos que, de alguma forma, descobrimos que o menor
valor entre os primeiros elementos de um vetor de tamanho . Podemos ento inferir
que o menor valor entre os primeiros elementos de o menor entre e .
Como j sabemos encontrar o mnimo em um vetor de 1 elemento ( ), sabemos
encontrar o mnimo em um vetor com 2 elementos; como sabemos encontrar o mnimo em
um vetor de 2 elementos, sabemos encontrar o mnimo em um vetor com 3 elementos.
Prosseguindo com o raciocnio, j temos um algoritmo para encontrar o menor valor em um
vetor de tamanho arbitrrio. Tendo um algoritmo, no temos mais medo do problema com
50.000 nmeros. Nosso trabalho ser programar o algoritmo; caber ao computador a sua
execuo.
A = [39. 24. 50. 42. 28. 8. 62. 34. 70. 52.];
Figura 38: Seis primeiros passos do algoritmo que encontra o menor valor presente em um vetor
Um algoritmo dito correto quando atende sua especificao. Dois algoritmos corretos
podem satisfazer uma mesma especificao, mas diferir substancialmente na eficincia (gasto
de tempo e de recursos computacionais como memria) com que realizam a transformao de
informao desejada. O termo complexidade empregado para designar a eficincia (ou
melhor, o inverso da eficincia) de um algoritmo para a soluo de um problema.
A complexidade de algoritmos estudada inicialmente com dois problemas clssicos da cincia
da computao: a ordenao dos elementos de um vetor e a busca por um elemento de um
vetor com valor igual a uma chave dada. Para cada um desses problemas so vistos algoritmos
que diferem em sua complexidade.
Encontrar uma raiz de uma funo ou resolver um sistema de equaes lineares so exemplos
de problemas numricos que um cientista ou engenheiro frequentemente tem que resolver.
Ns veremos alguns exemplos de algoritmos que resolvem problemas desse tipo, e tambm
alguns cuidados que devem ser tomados ao se desenvolver programas para estas aplicaes.
Algoritmos com melhor complexidade so fruto de engenho e arte de seus projetistas. Existem
entretanto problemas cuja soluo algortmica intrinsecamente difcil, no sentido em que
no existem boas solues para eles. A Parte III e o curso se encerram com exemplos de
problemas computacionalmente difceis, e de problemas para os quais simplesmente no
existe nenhum algoritmo que os resolvam para todos os casos.
2 Organizao de Computadores
2.1 Bits e cdigos
Como j dissemos, informao simblica exige convenes de interpretao. Qualquer pessoa
pode dar a um conjunto de bits a interpretao que bem entender, mas a escolha de um
cdigo pode ter conseqncias importantes.
ASCII e UNICODE. Para a comunicao de dados entre computadores a adoo de cdigos com
aceitao mais ampla traz diversas vantagens. O cdigo ASCII American Standard Code for
Information Interchange uma dessas convenes de ampla aceitao em toda a indstria
da computao.
A Tabela 3 mostra partes do cdigo ASCII, adotado desde os anos 60 para a representao de
caracteres como A, a, (, +, etc., para o espao em branco (sim, o espao exige uma
representao), e para os chamados caracteres de controle, como line feed, para indicar uma
troca de linhas. O cdigo ASCII oficial usa 7 bits, o que permite combinaes. Tendo
sido proposto por norte-americanos no incio da era dos computadores, no de se estranhar
que ali no haja proviso de cdigo para caracteres acentuados ou cedilhas. Estes so
contemplados no cdigo ASCII estendido, que usa 8 bits para representar 256 caracteres.
n 0 1 2 3 4 5 6 7 8 9 10
n
2 1 2 4 8 16 32 64 128 256 512 1024
O decimal 123 pode ser representado em binrio por 1111011, utilizando apenas 7 bits. Esta
representao vem do fato que .
Tabela 5: Representao dos nmeros de 0 a 15 como binrios sem sinal de 4 bits
Decimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Binrio 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
A converso de para pode ser feita com o seguinte mtodo para converso
binrio-decimal:
Ns precisamos expressar 123 como uma soma de potncias de 2. Para isso,
procuramos em uma tabela de potncias de 2 (como a Tabela 4; a tabela deve chegar
at uma potncia de 2 maior que o nmero a ser convertido) o maior valor que no
exceda 123 o que, no caso, 64. Temos .
Temos agora que expressar 59 como uma soma de potncias de 2. Na Tabela 4, a
maior potncia de 2 que no excede 59 32. Repetindo o raciocnio, temos
.
Desta forma progredimos at que a parcela a ser expressa como soma de potncias de 2 seja
igual a zero.
Tabela 6: Converso do decimal 123 para binrio
A converter 123 59 27 11 3 1 0
Potncia de 2 64 32 16 8 2 1
Um uso comum de nmeros representados como binrios sem sinal o sistema RGB (Red,
Green, Blue) para a codificao da cor associada a um pixel um ponto em um monitor com
os valores dos nveis de intensidade das cores primrias componentes vermelho, verde e azul.
Para cada uma dessas cores utiliza-se um byte (8 bits), o que permite representar nveis de
intensidade entre 0 e 255. Essa preciso considerada satisfatria para a nossa acuidade
visual.
Figura 39: Uso de binrios sem sinal para a representao dos nveis de intensidade das cores primrias vermelho
(Red), verde (Green) e azul (Blue), conhecido como RGB
Sinal e Amplitude. Como computadores s usam bits, ns no podemos usar um sinal - para
indicar que um valor negativo. Temos que usar bits para codificar essa informao. A
codificao para nmeros negativos conhecida como sinal e amplitude bastante natural.
Basta tomar o bit mais esquerda e interpret-lo como o sinal do nmero: se for 0, o nmero
cuja amplitude representada pelos bits restantes positivo, e se for 1, negativo. Portanto, se
tivermos 8 bits, o bit mais esquerda ser usado para codificar o sinal. Os 7 bits restantes nos
permitem representar amplitudes entre 0 e 127, ou seja, podemos, com os 8 bits, representar
os inteiros entre -127 e +127. Repare que zero tem duas representaes: 10000000 e
00000000.
Codificao com Deslocamento. Uma outra possibilidade para representar nmeros negativos
est ilustrada na Tabela 7. A conveno adotada de interpretar um conjunto de bits como a
representao de um valor igual ao valor de sua interpretao como binrio sem sinal,
deslocado por um fator a ser subtrado.
Tabela 7: Representao de nmeros negativos por deslocamento
Complemento de 2
Bits
Valor
b2 b1 b0
0 0 0 0
0 0 1 1
0 1 0 2
0 1 1 3
1 0 0 -4
1 0 1 -3
1 1 0 -2
1 1 1 -1
que a representao de -2. Isso permite aos fabricantes aproveitar para fazer subtraes o
mesmo circuito utilizado para fazer somas, com acrscimos mnimos de hardware.
Ponto Flutuante. A representao em um nmero limitado de bits de valores muito grandes
ou muito pequenos utiliza mecanismos para sua codificao similares aos que usamos na
notao cientfica com potncias de 10. O nmero de Avogadro, por exemplo, notado por
, e o dimetro de um tomo de hidrognio de metros. Para o nmero
de Avogadro ns dizemos que a mantissa 6,02 e o expoente, 23. A codificao de nmeros
em ponto flutuante atribui a alguns dos bits do nmero o significado de um expoente no de
10 mas de 2, como no poderia deixar de ser.
Existe um padro para ponto flutuante de aceitao total pela indstria que o IEEE 754. Para
nmeros de preciso simples, o IEEE 754 utiliza 32 bits, sendo 1 bit para o sinal (0 = positivo, 1
= negativo), 8 para o expoente e 23 para a mantissa. Para preciso dupla so 64 bits: 1 para o
sinal, 11 para o expoente e 52 para a mantissa. Expoentes negativos so representados pela
conveno de deslocamento que j vimos. Notando por o sinal, por o valor do expoente
interpretado como um binrio sem sinal, e por o valor da mantissa, tambm interpretada
como um binrio sem sinal, o valor representado por um nmero em ponto flutuante padro
IEEE 754 dado por
onde o deslocamento usado para expressar expoentes negativos, valendo 127 para
preciso simples e 1023 para preciso dupla.
A Figura 40 mostra um nmero em ponto flutuante de 32 bits.
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 7 6 5 4 3 2 1 0 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 1 1 0 1 0 1 0 1 1 1 1 0 1 1 1 0 1 0 1 1 1 0 1 0 0 0 1 0 0 0 1
4194304
2097152
1048576
262144
131072
65536
16384
4096
2048
1024
128
256
64
16
16
-1
0
4
0
1
0
0
0
0
0
0
1
213 7822609
-6,052450558E+32
O padro IEEE 754 reserva expoentes s com 1s e s com 0s para a representao de valores
especiais como ou NAN (Not a Number), que so necessrios para a comunicao de
resultados de certas operaes ou do clculo de algumas funes. A referncia (Hollasch,
2005) tem um bom resumo do padro.
Em 1854 o matemtico ingls George Boole props uma lgebra para o clculo da validade de
expresses formadas por proposies lgicas. Essa lgebra chamada hoje de lgebra
Booleana, e constitui a base para o projeto de circuitos digitais. Ela trabalha com variveis
lgicas, isto , com variveis que podem ter somente os valores verdadeiro ou falso, ou 1 ou 0.
As operaes fundamentais da lgebra de Boole so NO, E e OU, mais conhecidas pelas
palavras em ingls NOT, AND e OR. Essas operaes fundamentais, ou melhor, composies
dessas operaes fundamentais constituem as nicas transformaes feitas por qualquer
computador sobre bits.
a NOT a a b a OR b a b a AND b
0 1 0 0 0 0 0 0
1 0 0 1 1 0 1 0
1 0 1 1 0 0
1 1 1 1 1 1
A Tabela 9 mostra as definies dessas operaes. O que se v nas tabelas bastante intuitivo:
A operao de negao (NOT) simplesmente inverte o valor de entrada;
A operao OR tem como resultado 1 se pelo menos uma das entradas for igual a 1, e
s igual a 0 quando todas as entradas forem iguais a 0;
Inversamente, a operao AND tem 0 como resultado se qualquer uma das entradas
for igual a 0, e s igual a 1 quando todas as entradas forem iguais a 1.
Circuitos digitais que implementam operaes booleanas so conhecidos como portas lgicas.
A Figura 42 mostra um diagrama de circuito simulado no Logisim contendo desenhos adotados
por conveno para entradas, sadas e portas NOT, AND e OR e suas conexes.
Porta NOT
Porta AND
Porta OR
Entrada
Sada
Figura 42: Portas lgicas, entradas e sadas em um diagrama de circuito simulado no Logisim
Voltagem
Voltagem naEntrada
de Controle
Voltagem
na Sada
Figura 44: Um transistor
Um transistor tem 3 pinos: um controle, uma entrada e uma sada. Em circuitos digitais o seu
funcionamento se d somente nas seguintes situaes:
quando a voltagem aplicada ao controle alta (para algumas tecnologias, 5 volts), o
transistor um condutor perfeito, e as voltagens na entrada e na sada so
necessariamente iguais;
quando a voltagem aplicada ao controle baixa (0 volts, digamos), o transistor um
isolante perfeito, e as voltagens na entrada e na sada podem diferir.
Vejamos inicialmente como uma porta NOT implementada com a utilizao de um
transistor. Suponhamos que estamos representando o smbolo 0 por uma voltagem baixa e o
smbolo 1 por uma voltagem alta. Como mostrado na Figura 45, uma fonte de voltagem alta
ligada entrada do transistor, atravs de uma resistncia, enquanto a sada do transistor
ligada um ponto de terra. A varivel que desejamos negar, , ligada ao controle do
transistor. O resultado do circuito, , obtido no ponto entre a resistncia e a entrada do
transistor.
Fonte V= 5
a
(voltagem alta)
1
a
0
Terra V= 0
(voltagem baixa)
Figura 45: Uma porta NOT invertendo a = 0. Como a = 0, o transistor funciona como isolante perfeito
Fonte V= 5
a
(voltagem alta)
0
a
1
Terra V= 0
(voltagem baixa)
Figura 46: Porta NOT invertendo a = 1. O transistor funciona como condutor perfeito
0 (a + b)
a
1
b
0
Terra
Figura 47: Uma porta NOR com transistores
Uma porta NOR construda com o arranjo de transistores mostrado na Figura 47; no
difcil ver que o ponto s ter o valor 1 (voltagem alta) quando os dois transistores do
arranjo estiverem funcionando como isolantes, o que s ocorre quando e .
Fonte
1 (a.b)
a
1
b
0
Terra
Figura 48: Uma porta NAND implantada com transistores
Uma porta NAND construda de forma similar, mas com os transistores ligados em srie,
como mostra a Figura 48. Aqui a sada s ser igual a zero quando tivermos e
, valores que fazem com que a sada esteja conectada ao ponto de terra.
Fonte Fonte
a.b
0
a
1
b Terra
0
NAND NOT
Para obter uma porta AND usando transistores basta inverter a sada de uma porta NAND,
como mostrado na Figura 49. Uma porta OR pode tambm ser obtida conectando a sada de
uma porta NOR com a entrada de uma porta NOT.
Para o nosso primeiro circuito, vamos comear colocando duas portas AND, clicando sobre o
smbolo correspondente na barra de ferramentas, e posicionando as portas na rea de
desenho, como mostrado na Figura 51. Repare na tabela de atributos, que exibe e permite a
edio de dados relativos ao elemento selecionado no caso, a porta AND inferior.
Depois, usando ainda a barra de ferramentas, vamos colocar uma porta OR e duas NOT,
posicionando-as conforme a Figura 52.
Para colocar fios ligando entradas, portas e sadas, utilize a ferramenta de seleo em
destaque na Figura 54. Fios sempre seguem caminhos horizontais ou verticais (chamado
caminho Manhattan), e nunca em diagonal.
Seu circuito ficar mais fcil de ser compreendido se voc acrescentar textos, usando a
ferramenta A em destaque na Figura 56. Voc pode alterar as caractersticas da fonte
(tamanho, negrito ou itlico, etc.) editando os atributos do texto selecionado.
Textos podem ser colocados em qualque posio na rea de desenho, mas muitas vezes
melhor coloc-los como "labels" de elementos de circuito, como entradas, portas lgicas e
sadas. O label acompanha o elemento quando este movido para outra posio. Para isto,
selecione o elemento, e preencha o campo Label na tabela de atributos, como mostrado na
Figura 56.
Para testar o seu circuito, use a ferramenta de simulao a mozinha em destaque na Figura
57. Utilize-a sobre as entradas do circuito para alterar o seu valor. Explore todas as
combinaes possveis de valores para a e b, verificando a sada para completar a Tabela 10.
Tabela 10: Complete com os valores produzidos pelo seu circuito XOR
a b a XOR b
0 0
0 1
1 0
1 1
Circuitos podem ser salvos em arquivos para uso posterior. Para salvar o seu circuito, use a
opo File/Save do menu do Logisim, escolha um nome para o arquivo e um diretrio, e salve-
o. Para voltar a trabalhar com o arquivo, use File/Open.
Para introduzir elementos de circuito com outras orientaes, clique sobre a porta desejada, e
depois altere o campo Facing na tabela de atributos, conforme mostrado na Figura 58.
Com isso ns esperamos que voc tenha adquirido os elementos bsicos para o uso do
Logisim. Voc pode descobrir muito mais lendo a ajuda ou explorando diretamente a
ferramenta.
Entradas
1 bit cada
a b
Circuito Somador
1 bit
Notao comum para
Sadas conjuntos de bits:
s1 s0 0 o ndice do bit
menos significativo
Para especificar exatamente o que desejamos deste circuito, vamos utilizar uma tabela da
verdade. Uma tabela da verdade apresenta o valor de uma ou mais funes lgicas as sadas
do circuito correspondendo a cada combinao possvel de valores das variveis de entrada.
A Figura 61 mostra a tabela da verdade para a soma de duas variveis de 1 bit.
Sadas:
2 funes
Entradas lgicas das
mesmas
variveis
Todos os Resultados da
valores soma em
possveis para binrio sem
as entradas sinal
Figura 61: Tabela da Verdade para soma de duas variveis de 1 bit
0 0 0 1 0 0
0 0 1 1 1 1
0 1 0 1 1 1
0 1 1 1 1 1
1 0 0 0 0 0
1 0 1 0 1 0
1 1 0 0 1 0
1 1 1 0 1 0
Figura 62: Tabela da verdade para a expresso
Mas o nosso problema no bem esse. Ns temos uma tabela da verdade e, para obter um
circuito lgico para uma das funes de sada a partir de uma tabela da verdade preciso:
conseguir uma expresso lgica equivalente tabela da verdade, e
construir o circuito equivalente expresso lgica.
Uma expresso lgica e uma funo definida por uma tabela da verdade so equivalentes
quando para qualquer combinao de valores das variveis de entrada, os valores da funo e
os valores da expresso so iguais. Por exemplo, a funo definida pela
Tabela 11 equivalente expresso .
x y f(x,y)
0 0 1
0 1 0
1 0 0
1 1 1
Um mtodo genrico para se obter uma expresso lgica para uma funo definida por uma
tabela da verdade consiste em fazer um OR de termos que s tm o valor 1 para cada
combinao das variveis de entrada para a qual o valor da funo igual a 1.
x y f(x,y)
0 0 1
0 1 0
xy + xy
1 0 0
1 1 1
s0 = ab + ab
s1 = ab
Figura 64: Expresses lgicas para um somador de duas variveis de 1 bit
Retornando ao problema do somador de 1 bit, temos duas funes para as quais queremos
encontrar expresses lgicas equivalentes. Na Figura 64 vemos que, para a funo , temos
apenas o 1 da ltima linha a cobrir, o que feito pelo termo , e para a funo , temos um
1 na segunda linha, coberto pelo termo , e outro 1 na terceira linha, coberto pelo termo
. Ou seja, as expresses lgicas que desejamos so e . A Figura 65
mostra um circuito que implementa essas expresses lgicas. Este circuito conhecido como
circuito meia-soma, por contraste com o circuito soma-completa que veremos a seguir.
ab
ab
ab
Figura 65: Circuito lgico para soma binria de 1 bit, ou circuito meia-soma
Uma soma de nmeros binrios similar soma decimal que aprendemos na escola primria.
Para fazer uma soma na base 10 ns somamos algarismo por algarismo, da direita (menos
significativos) para a esquerda (mais significativos). Quando a soma de dois algarismos excede
9, colocamos como resultado daquela coluna somente o seu dgito mais significativo, e
acrescentamos 1 (o vai-um) na soma da coluna seguinte (Figura 66).
Vai-um 1 1
a 2 7 7 6
b 4 7 9 1
a+b 7 5 6 7
Figura 66: Soma em decimal
Para somar dois nmeros binrios o procedimento anlogo. Somamos bit a bit, da direita
para a esquerda e, quando a soma de uma coluna excede 1, colocamos como resultado da
coluna somente o bit mais significativo de sua soma, e temos um vai-um para a coluna
seguinte. A Figura 67 mostra o processo do clculo de 1011101+1001110.
Vai-Um
1 0 1 1 1 0 0
Parcelas
1 0 1 1 1 0 1
1 0 0 1 1 1 0
1 0 1 0 1 0 1 1
Soma
Figura 67: Exemplo de soma de binrios
Ns vamos usar essa aritmtica para construir um circuito somador de vrios bits. A idia
construir um mdulo que faa a operao de uma das colunas da soma. O somador ter tantos
deste mdulo quantas forem as colunas, ou seja, quantos forem os bits das parcelas.
vai-um vem-um
soma SC a
b
Circuito
Soma-Completa
Igual a 1 vem-um do
quando a bit menos
soma tiver significativo
5 bits sempre
zero
Figura 69: Arranjo em cascata de mdulos para um somador de 4 bits
A Figura 71 mostra um circuito de soma completa. Repare que a sada vai-um dada pela
expresso simplificada
a2 a1 a0 b2 b1 b0
0 0 0 0 0 1
0 0 1 0 1 0
0 1 0 0 1 1
0 1 1 1 0 0
1 0 0 1 0 1
1 0 1 1 1 0
1 1 0 1 1 1
1 1 1 0 0 0
Entre com as variveis na ordem (da esquerda para a direita) em que voc deseja que elas
apaream na tabela da verdade. No caso, primeiro a2, depois a1 e depois a0.
Para as variveis de sada o procedimento similar. Selecione a aba Outputs, e entre um a um
com os nomes das variveis de sada, na ordem em que voc deseja que apaream na tabela
da verdade. No caso, primeiro b2, depois b1 e depois b0.
Agora preciso entrar com os valores da tabela da verdade. Clique sobre a aba Table, e voc
ver uma tela como a da Figura 76.
Depois, entre com os valores apropriados, clicando uma ou mais vezes sobre cada um dos x na
tabela, at obter o valor desejado. Se passar do ponto, clique novamente. Faa isto at chegar
tabela da Figura 77, onde voc pode reparar que em cada linha, b2b1b0 = a2a1a0+1, exceto
na ltima, onde seguimos a conveno j mencionada.
Agora s clicar sobre Build Circuit, e o circuito SomaUm est pronto! Confira com a tela da
Figura 78 o circuito que voc construiu.
Teste o seu circuito com os valores binrios correspondentes aos valores decimais 2, 5 e 7,
verificando se as sadas interpretadas como binrios sem sinal correspondem a 3(= 2+1),
6(=5+1) e 0(pois 710 = 1112).
importante voc reparar que o Logisim criou o circuito SomaUm como um sub-circuito, o que
indicado no painel de navegao veja a seta na Figura 78. Ns vamos agora utilizar o
SomaUm como um componente para construir o circuito SomaTrs, o que pode ser feito
ligando trs circuitos SomaUm em cascata.
Para isto clique com o boto direito do mouse sobre o sub-circuito main, e escolha View
Circuit. Voc ver um circuito vazio. Agora clique com o boto esquerdo do mouse sobre o
sub-circuito SomaUm, e coloque no painel de desenho 3 bloquinhos conforme a figura abaixo.
O Logisim oferece este componente, na biblioteca Input/Output. Cada um dos pinos acente um
dos filamentos, com exceo de um pino que acende um ponto decimal, que no vamos usar
aqui.
Lower Left
Lower Right
Para isso, abrimos a janela Combinational Analysis do Logisim, e construmos uma tabela da
verdade com 4 entradas, a3, a2, a1 e a0, e com 7 sadas, UL, U, C, UR, LL, P, L e LR. Para cada
linha colocamos 1 nas sadas correspondentes aos filamentos que, acesos, compem o dgito
hexadecimal formado pelos bits de entrada. A tabela final est mostrada na Figura 83.
Figura 83: A tabela da verdade completa para o display hexadecimal, com destaque para a determinao das
sadas para formar um F
Feito isso, basta apertar Build Circuit para obter o circuito da Figura 84. O circuito parece
complicado? Pode ser, mas isso no um problema. O circuito foi construdo
automaticamente, a partir de uma tabela da verdade, usando algoritmos do Logisim que so
melhorias do mtodo que vimos para obteno de somas cannicas. Isso nos garante a sua
correo. E ele pode ser usado como um mdulo, esquecendo completamente seus detalhes,
como fizemos na Figura 82.
Figura 84: Circuito gerado automaticamente pelo Logisim para o controlador de display hexadecimal
a b
Comparador
Vimos na seo 2.2.4 que circuitos lgicos podem realizar operaes aritmticas. Vamos agora
atacar o problema de construir circuitos lgicos que permitam comparar duas variveis e
aMaior 0 0 0 0 1 1 1 1 1
abIguais 1 1 1 1 0 0 0 0 0
bMaior 0 0 0 0 0 0 0 0 0
a 0 1 1 1 1 0 0 0
b 1 1 1 0 1 1 1 0
aMaior 0 0 0 0 0 0 0 0 0
abIguais 1 0 0 0 0 0 0 0 0
bMaior 0 1 1 1 1 1 1 1 1
a 1 1 1 0 1 0 1 0
b 1 1 1 0 1 0 1 0
aMaior 0 0 0 0 0 0 0 0 0
abIguais 1 1 1 1 1 1 1 1 1
bMaior 0 0 0 0 0 0 0 0 0
Figura 86: Casos de comparao entre as entradas a e b.
fcil ver que, ao comparar dois binrios de mesmo tamanho, sem sinal, devemos comparar
bit a bit, comeando com o bit mais significativo. Na primeira diferena, j podemos concluir
que a parcela com o bit igual a 1 definitivamente a maior, e os bits restantes, que so menos
significativos, no interessam para o resultado final. A Figura 86 mostra trs casos de
comparao de entradas e , cada uma com 8 bits. No primeiro caso as entradas diferem no
quarto bit mais significativo, e . No segundo caso as entradas j diferem no primeiro bit
mais significativo, e . No terceiro caso as entradas so iguais.
Para construir um circuito que faa a comparao de binrios sem sinal ns precisamos de um
comparador de 1 bit que leve em considerao a possibilidade do resultado j ter sido
estabelecido por algum bit mais significativo.
Bit corrente
a
Amaior
b
Mdulo
aMaior Bmaior
Comparador
bMaior de 1 bit
ABiguais
abIguais
Vm do comparador Vo para o
esquerda comparador direita
Figura 87: Entradas e sadas para um mdulo comparador de 1 bit
j feita com bits mais significativos que o bit em questo vm as entradas aMaior, bMaior e
abIguais. A Figura 88 mostra o arranjo de mdulos que compem um comparador de 4 bits.
Entrada b Entrada a
Temos um mdulo comparador para cada bit das variveis de entrada. Cada mdulo
comparador tem cinco entradas:
Duas so os bits das entradas da coluna correspondente ao mdulo;
As trs outras so designadas por aMaior, bMaior e abIguais e, exceto para o
mdulo mais esquerda, so produzidas pelo mdulo comparador esquerda do
mdulo em questo. Elas tm o resultado da comparao j realizada com os bits mais
significativos e portanto, uma e somente uma dessas entradas poder ter o valor 1.
Para o mdulo mais esquerda, que corresponde ao bit mais significativo, abIguais
tem o valor 1.
A Figura 89 mostra as primeiras linhas de uma tabela da verdade para o mdulo comparador
de 1 bit; a tabela completa tem linhas. A coluna aMaior uma entrada desse
mdulo, enquanto a coluna Amaior uma sada. A mesma conveno usada para bMaior,
Bmaior, abIguais e ABiguais. Combinaes onde mais de uma dentre as variveis aMaior,
bMaior e abIguais tm o valor 1 ou em que todas as trs so iguais a 0 nunca devem ocorrer,
e o smbolo usado na tabela para indicar que os valores das sadas no tm interesse
nesses casos. O Logisim tira proveito disso para obter circuitos mais simples.
Estas sadas
vo para a
coluna direita
Estas
entradas
vm da
coluna
esquerda
x usado quando a
combinao de entradas
nunca ocorre o Logisim
simplifica o circuito
Figura 89: Tabela da verdade para um comparador de 1 bit
a, de address,
determina
qual entrada out = In0
ser quando a=0
encaminhada
para a sada
Out
out = In1
quando a=1
A Figura 91 mostra uma tabela da verdade para um multiplexador de 1 bit. Esse circuito tem
trs entradas: In0 e In1, que so as variveis fonte de informao, e o endereo a, que decide
qual dentre In0 e In1 ser conectada sada out.
out0 = In
quando a=0
a (address)
indica para
qual sada a
entrada In
ser copiada
out1 = In
quando a=1
Multiplexadores de 1 bit tambm podem ser usados como mdulos para a construo de
multiplexadores de mais bits, com o arranjo mostrado na Figura 94.
O binrio a1a0
designa qual
entrada fica
ligada sada
Demultiplexadores com uma largura de endereo (nmero de bits) maior tambm podem
ser obtidos com arranjos hierrquicos similares, como mostra a Figura 96.
DMX
1 bit
DMX
1 bit
DMX
1 bit
Complemento
do Bit
A entrada D Armazenado
fotografada no
instante em que o clock
passa de 0 para 1
Pino Auxiliar: Pino Auxiliar:
Impe 1 Impe 0
Figura 97: Um flip-flop tipo D
O circuito seqencial mais bsico conhecido pelo nome em ingls de flip-flop. Como
podamos esperar, um flip-flop capaz de armazenar um nico bit. Existem vrios tipos de flip-
flop, mas aqui ns s veremos flip-flops ditos do tipo D. A Figura 97 mostra um flip-flop tipo D
disponvel no Logisim, e que possui 5 pinos:
Pino D: onde fica a informao o Dado que pode vir a ser armazenada no flip-
flop;
Pino Clock: um pino que funciona como um obturador de uma mquina fotogrfica.
No exato instante em que o sinal aplicado ao Clock passa de 0 para 1, o flip-flop passa
a armazenar o valor corrente do pino Input. O nome clock vem do fato deste sinal
frequentemente se originar de uma fonte de tempo, como veremos mais tarde. Click
seria um nome mais adequado para a analogia com a mquina fotogrfica.
Pino Q: uma sada que tem o valor armazenado no flip-flop;
Pino Q: uma sada que tem o complemento do valor armazenado no flip-flop;
Pinos Set e Reset: so entradas auxiliares que facilitam a imposio de um valor para o
flip-flop. Essas entradas so normalmente usadas para inicializao ou re-inicializao
do flip-flop.
5 1
Clock
4 0
3 1
D
2 0
1 1
Q
0 0
-1
1 2 3 4 5 6 7 8 9 10 11 12 13
Tempo
Figura 98: Carta de tempo para um flip-flop tipo D. As setas destacam os instantes de subida do clock, quando a
entrada D copiada pelo flip-flop.
A Figura 98 mostra um grfico uma carta de tempo que ilustra um exemplo de evoluo
temporal de um flip-flop tipo D, onde:
no instante 1 as entradas D e Clock valem 0, assim como a sada Q;
nos instantes 2, 3 e 4 respectivamente a entrada D muda de 0 para 1, de 1 para 0 e de
0 para 1 novamente, sem que isso afete a sada Q, pois a entrada Clock permanece em
0 durante esse intervalo;
no instante 5 a entrada Clock sobe, mudando de 0 para 1. a este sinal que o flip-flop
reage, copiando (fotografando) a entrada D. Com isso o bit armazenado muda
tambm de 0 para 1;
no instante 6 a entrada Clock desce, mas isso no afeta o estado do flip-flop;
nos instantes 7, 8 e 9 a entrada D oscila novamente, sem afetar o estado do flip-flop;
no instante 10 o sinal do Clock sobe, e a sada Q passa para 0, copiando o valor de D
nesse instante;
E por a vai.
Clock Sadas
nico para
os 4 FFs
Entradas
Valor
armazenado,
em
hexadecimal
Registradores
Largura de
dados
Figura 101: Dois circuitos equivalentes. No circuito de cima, fios e registradores tm 1 bit de largura; no de baixo,
4 bits
Na Figura 101 ns vemos dois circuitos equivalentes, cada um com dois registradores de 4 bits
conectados. O circuito de cima utiliza somente elementos de largura de 1 bit, com os quais j
estamos familiarizados. O de baixo utiliza entradas, sadas, registradores e cabos de 4 bits de
largura. Seu desenho por isso mesmo muito mais simples e, portanto, de mais fcil
compreenso. A largura de bits de componentes como registradores, entradas e sadas
controlada pelo usurio, usando o campo data width no painel de atributos, como na Figura
100. O Logisim facilita a nossa vida dando a cabos a largura de bits dos componentes aos quais
o cabo se conecta, e alertando o usurio nos casos de incompatibilidade.
5 bits
2 bits
8 bits
1 bit
Figura 102: Uma bifurcao de um cabo de 8 bits em um de 5 bits, outro de 2 e um terceiro de 1 bit de largura. O
retngulo esquerda uma ampliao do painel de atributos da bifurcao
O Logisim oferece ainda bifurcaes (splitters) que permitem dirigir os bits de um cabo com
largura maior para outros de largura menor, como mostrado na Figura 102.
A todo instante, no
mximo um controlled
buffer pode ter o controle
do barramento
O dado no barramento
igual sada com o
controlled buffer ligado
Nos circuitos que vimos at agora um cabo s pode ser usado para conectar uma sada de um
componente a uma ou mais entradas de outros componentes. Essa restrio vem por um lado
da falta de sentido lgico nesse tipo de conexo: se uma das sadas tem 0 e outra 1, qual valor
fica no barramento? Por outro lado, vem tambm dos circuitos reais: se uma de duas sadas
conectadas a um cabo tem o valor 0 e outra tem o valor 1, temos uma voltagem alta ligada
diretamente a uma voltagem baixa, ou seja, um curto-circuito.
Um componente especial, o controlled buffer, permite fazer esse tipo de ligao, o que
simplifica muito o desenho de circuitos. Diversas sadas podem ser conectadas a um nico
cabo se essas conexes passarem por um controlled buffer. Este cabo compartilhado recebe o
nome de barramento. Todo controlled buffer tem, como o prprio nome indica, um pino de
controle que abre ou fecha a conexo com o barramento. O projetista de um circuito deve
cuidar para que, a qualquer instante, no mximo um dentre todos os controlled buffers ligados
a um mesmo barramento esteja aberto.
Colocar 7 no registrador A
Sinal Comentrio
In = 7 Coloca 7 na entrada In
In->Dbus = 1 A entrada In controla o barramento
A Clk = 1 O registrador A copia o barramento
A Clk = 0 Abaixa o clock do registrador A
In->Dbus = 0 Libera o barramento
Colocar 3 no registrador B
Sinal Comentrio
In = 3 Coloca 3 na entrada In
In->Dbus = 1 A entrada In controla o barramento
B Clk = 1 O registrador B copia o barramento
B Clk = 0 Abaixa o clock do registrador B
In->Dbus = 0 Libera o barramento
O circuito da Figura 103 permite que um dado na entrada In seja copiado por qualquer dos
registradores A, B ou C, e permite tambm que o valor em qualquer registrador seja copiado
por qualquer um dos outros registradores. Estes fluxos so controlados pelos sinais de clock
dos registradores e de controle dos controlled buffers. Dados so transferidos de um ponto
para outro ligando e desligando esses sinais em uma sequncia apropriada para a
transferncia desejada, como mostram os exemplos na Figura 104.
2.3.3 Memrias
O Logisim oferece memrias RAM (Random Access Memory) e ROM (Read Only Memory)
como componentes de sua biblioteca Memory. Memrias armazenam informaes como
conjuntos de bits chamados palavras. Cada palavra possui um endereo na memria. Uma
memria tem como atributos sua largura de dados, isto , o nmero de bits em cada palavra
da memria, e a largura do endereo. Com bits de endereo uma memria tem no mximo
palavras. No Logisim, a largura de bits do endereo determina tambm o tamanho da
memria, que tem exatamente palavras.
Memory Entrada e
Address tambm sada
Register de dados
Na subida,
copia D na
posio A
Figura 105: Uma memria RAM do Logisim em um arranjo com registradores e barramento
Exemplos de fluxos de dados realizveis com o circuito da Figura 105 so mostrados na Figura
106 e na Figura 107.
2.3.4 Acumuladores
Registrador
Acumulador
Circuito Soma
(combinatrio)
Um registrador pode ser usado como um acumulador, como mostrado na Figura 108. Neste
arranjo,
a entrada do acumulador alimentada por um circuito combinatrio que tipicamente
realiza operaes aritmticas ou lgicas, e
a sada do acumulador realimenta o circuito combinatrio, isto , a sada do
acumulador uma das entradas do circuito combinatrio.
Este arranjo permite, por exemplo, somar 10.000 nmeros, seqenciando as somas ao longo
do tempo.
Colocar 5 no Acumulador
Sinal Comentrio
Acc Clr = 1 Zera o acumulador
Acc Clr = 0 Abaixa o clear do acumulador
In = 5 Coloca 5 na entrada In
In->Dbus = 1 A entrada In controla o barramento
O acumulador copia a entrada, que a
Acc Clk = 1
sada do circuito de soma, sendo = 5
Acc Clk = 10 Abaixa o clock do acumulador
In->Dbus = 0 Libera o barramento
Figura 109: Exemplo de fluxo de dados realizvel pelo circuito da Figura 108
Exemplos de fluxos de dados realizveis com o circuito da Figura 108 esto mostrados na
Figura 109 e na Figura 110.
Soma 7 (111) ao contedo do Acumulador, e transfere
o resultado para o registrador Out
Sinal Comentrio
In = 7 Coloca 7 na entrada In
In->Dbus = 1 A entrada In controla o barramento
O acumulador copia a entrada, que a
sada do circuito de soma, sendo igual a 12
Acc Clk = 1
(0c em hexa), soma do valor do acumulador
com o do barramento
Acc Clk = 0 Abaixa o clock do acumulador
In->Dbus = 0 Libera o barramento
Acc->Dbus = 1 O acumulador controla o barramento
Out Clk = 1 O registrador Out copia o barramento
Out Clk = 0 Abaixa o clock do registrador Out
Acc->Dbus = 0 Libera o barramento
Figura 110: Outro exemplo de fluxo de dados realizvel pelo circuito da Figura 108
2.4 Processadores
2.4.1 Uma Calculadora
A Figura 111 mostra um circuito uma calculadora com diversos elementos ligados a um
barramento de 16 bits:
Registradores In e Out, ligados tambm a entradas e sadas de 16 bits
Um registrador de dados, o DR;
Uma memria principal com 32K palavras de 16 bits, tambm com 16 bits de
endereo;
Uma unidade lgico-aritmtica, que um circuito combinatrio com duas entradas,
uma ligada ao barramento e outra sada do acumulador. A ALU (Arithmetic and
Logical Unit) capaz de realizar somas, subtraes e comparaes entre suas duas
entradas. (Outras operaes que uma ALU poderia fazer incluem operaes lgicas
(AND, OR, etc.) e de deslocamento (shift) de bits.)
Um registrador acumulador ACC, alimentado pela sada de resultado de operao da
unidade lgico-aritmtica;
Um registrador de resultado de comparao Compare, tambm alimentado pela
ALU.
Temos ainda o registrador MAR, que alimenta a entrada de endereo da memria principal, e
que alimentado pelo barramento. A biblioteca Entrada/Sada do Logisim oferece leds,
pequenas lmpadas que foram acrescentadas ao circuito somente para acompanhamento
visual do registrador Compare. Cada registrador, assim como a memria principal, tem um
sinal de clock; cada sada para o barramento tem um sinal que controla a posse do
barramento.
As rotas de dados de uma calculadora como a da Figura 111 permitem controlar diversos
fluxos de dados diversas computaes envolvendo a memria RAM, as entradas e sadas, o
acumulador e os registradores de dados e de endereos. O controle do fluxo de dados feito
pelo usurio Logisim, que se encarrega de:
mudar de 0 para 1 ou de 1 para 0 os sinais de controle de posse de barramentos e de
cpia de registradores, na seqncia adequada ao efeito desejado, e de
fornecer operandos atravs do registrador Input.
Vamos usar a calculadora para resolver um problema simples de transformao de
informao: queremos somar os contedos das posies 1 e 2 da memria, e colocar o
resultado na posio 3. Podemos fazer isso atravs das etapas:
1. Carregar no acumulador o contedo da posio 1 da RAM
2. Somar ao acumulador o contedo da posio 2 da RAM
3. Armazenar o contedo do acumulador na posio 3 da RAM.
Na Figura 112 e na Figura 113 esto mostrados os sinais de controle e, em destaque, as
entradas de operandos necessrias para essa computao.
ACC_Clear = 1
ACC_Clear = 0
Input = 1 Input = 2
In_Clk = 1 In_Clk = 1
In_Clk = 0 In Clk = 0
In->Bus = 1 In->Bus = 1
Carrega no acumulador o
MAR_Clk = 1 MAR_Clk = 1
contedo da posio 1 da RAM Soma ao acumulador o
MAR_Clk = 0 MAR_Clk = 0
contedo da posio 2 da RAM
In->Bus = 0 In->Bus = 0
RAM->Bus = 1 RAM->Bus = 1
ACC_Clk = 1 ACC_Clk = 1
ACC_Clk = 0 ACC_Clk = 0
RAM->Bus = 0 RAM->Bus = 0
Figura 112: Sinais de controle e entrada de operandos para as etapas 1 e 2
Input = 3
In_Clk = 1
In_Clk = 0
In->Bus = 1
MAR_Clk = 1 Armazena o contedo do
MAR_Clk = 0 acumulador na posio 3 da
In->Bus = 0 RAM
ACC->Bus = 1
RAM_Clk = 1
RAM_Clk = 0
ACC->Bus = 0
Figura 113: Sinais de controle e entrada de operandos para a etapa 3
A partir do sinal bsico fornecido por um clock, circuitos como registradores circulares podem
fornecer outros sinais, que podem ser usados para coordenar ao longo do tempo o fluxo de
dados de um circuito.
A Figura 115 mostra um registrador circular formado por trs flip-flops tipo D alimentados por
um clock. O cabeamento tal que a sada do FF t0 est ligada entrada D do FF t1, a sada do
FF t1 entrada do FF t2, e a sada do FF t2 est ligada entrada do FF t0, em um arranjo
circular. O registrador inicializado atravs do pino Reset, que coloca 1 no flip-flop t0, e 0 nos
demais. A cada subida do clock cada FF copia a sua entrada, o que faz com que o 1 inicialmente
armazenado no FF t0 passe para o FF t1, depois para o t2, retornando ento ao FF t0.
t2
t1
t0
Clock
Reset
2.4.3 Micro-instrues
Um processador deve ser um circuito digital com comportamento flexvel, comandado por
alguma coisa que chamamos de programa. Um programa produzido por um ser humano,
que necessita resolver um problema de transformao de informao. Trocando-se o
programa, troca-se o comportamento do processador; isso no deve envolver modificaes no
circuito, pois a idia que essa troca de programa seja uma operao de fcil realizao.
Se isso o que queremos, um programa s pode ser (ao menos em seu formato final)
informao codificada em bits, que deve ser carregada em alguma memria para sua
execuo. Para eliminar a necessidade de interveno humana durante a execuo do
programa, uma unidade de controle deve ser adicionada calculadora. Ao executar um
programa, a unidade de controle deve se encarregar das tarefas antes executadas pelo
operador Logisim, que so:
emitir sinais de controle, e
fornecer operandos.
Vamos construir uma primeira unidade de controle usando as seguintes idias:
para sua execuo, o programa deve ficar armazenado como uma seqncia de
palavras em uma memria RAM; por razes que veremos em seguida, chamamos cada
palavra desses programas de micro-instruo;
a cada sinal de controle da calculadora deve corresponder um bit nas micro-
instrues;
a unidade de controle implementa um ciclo de leitura em seqncia de micro-
instrues da memria com o programa;
em cada ciclo, os bits de cada palavra lida so encaminhados para as sadas da unidade
de controle, que so ligadas aos pontos de controle da (ex-) calculadora.
Sinais Micro-instruo
Compare_Clk
ACC_Clear
RAM_Bus
ACC->Bus
In->Dbus
MAR_Clk
RAM_Clk
Subtract
DR->Bus
ACC_Clk
Comentrios
Out_Clk
DR_Clk
In_Clk
0 0 0 0 0 0 0 0 0 0 0 0 1 ACC = 0
0 0 1 0 0 0 0 0 0 0 0 0 0 MAR = Bus
0 0 0 1 0 0 0 0 0 0 0 0 0 Bus = RAM
0 0 0 1 0 0 0 0 0 0 0 1 0 ACC = ACC + Bus
Figura 117: Codificao de sinais de controle em micro-instrues
A Figura 117 mostra como podemos especificar micro-instrues por meio de uma tabela onde
cada coluna um dos sinais de controle do circuito da Figura 111. Cada linha da tabela
corresponde a uma micro-instruo, e as micro-instrues sero executadas sequencialmente
pela unidade de controle.
Contador de
Programa armazena o
endereo da prxima Memria de
micro-instruo a ser Programa
executada
Figura 118: Circuito para gerao automtica de sinais de controle segundo um programa
Ns vamos agora mostrar um circuito que gera automaticamente sinais de controle, ignorando
por enquanto o problema do fornecimento de operandos. No circuito da Figura 118 ns
vemos:
uma memria RAM onde fica armazenado um programa,
sadas de sinais de controle, ligadas diretamente sada da memria de programa, e
um contador de programa, denominao que se d a registradores com a funo de
controlar o endereo aplicado a memrias de programa, e que contm ou o endereo da
instruo em execuo, ou o endereo da prxima instruo a ser executada.
O contador de programa PC (Program Counter) tem o seu valor incrementado de 1 a cada
subida do clock, o que faz com que a sada de dados da memria exponha em sucesso as
micro-instrues. Como cada micro-instruo determina o valor dos sinais de sada, ns temos
o que queramos: a gerao automtica de sinais de controle, guiada por um programa
carregado na memria.
Soma 1
Registrador
A Figura 119 mostra o circuito do contador de programa, que um registrador cuja sada est
ligada a um circuito de soma , cuja sada realimenta a entrada do registrador. A outra parcela
da soma sempre igual a 1, o que produz o efeito que desejamos: a cada subida do clock, o
valor do PC incrementado de 1. O circuito possui tambm uma entrada Reset que zera o
PC.
Dominado o problema da emisso dos sinais de controle, vamos agora ver como eliminar a
necessidade de interveno do operador Logisim tambm na entrada de valores dos
operandos (endereos da memria, valores a serem adicionados ou carregados no
acumulador, etc.). Ns queremos agora permitir que operandos j possam ser especificados no
programa, e que estes operandos sejam fornecidos pela unidade de controle (ex-)
calculadora nos momentos adequados.
Sinal Adicional
23 22 23 2022 192118 2017 19
21 16 18
15 17
14 16
13 15
12 14
11 13 coloca
10 129 118 107 96 85 74 63 52 41 30 2 1 0
Sinais Operando no
Sinais
Barramento
Bit 23
Compare_Clk
Compare_Clk
Operando?
Operando?
Oper->Bus
Oper->Bus
ACC_Clear
ACC_Clear
indica se a
RAM_Bus
ACC->Bus
RAM_Bus
ACC->Bus
In->Dbus
MAR_Clk
RAM_Clk
In->Dbus
MAR_Clk
RAM_Clk
Subtract
Subtract
DR->Bus
DR->Bus
ACC_Clk
ACC_Clk
Operando nos
Out_Clk
Out_Clk
DR_Clk
DR_Clk
In_Clk
In_Clk
palavra 16 bits menos
codifica um significativos = 11 1
operando1 1
1 1 2
1
1 11 1
1 1
1 1 1 1
1 1 1 1
1 1
1 11 1
1 1
1 1 1 1
1 1 1 1 1 1
1 1
Figura 120: Codificao de operandos
1 em
11 micro-instrues
1
1 1
1 1
A Figura 120 mostra uma forma de se codificar operandos em1micro-instrues. 1
Por motivos
de ordem prtica, ns adotamos micro-instrues de 24 bits. Para indicar que uma micro-
instruo codifica um operando, ns vamos utilizar o bit mais significativo, o bit 23. Se este bit
for igual a 0, os bits restantes so interpretados como sinais de controle; se for igual a 1, os 16
bits menos significativos so a codificao em binrio de um operando (o barramento da
calculadora tem 16 bits de largura).
A unidade de controle dever ter uma sada com o valor do operando, ligada ao barramento
da calculadora, e utilizando, como todas as outras ligaes de sada para o barramento, um
controlled buffer para evitar conflitos. Este controlled buffer comandado por um sinal, que
deve ser adicionado aos sinais j emitidos pela unidade de controle.
J temos agora condies de mostrar o nosso primeiro processador, capaz de executar micro-
instrues em sequncia, com sinais de controle e operandos fornecidos por uma unidade de
controle. A Figura 121 mostra o circuito principal da CPU-0, nome que demos a este
processador. Para compreender a CPU-0, voc deve primeiramente reparar que podemos
dividi-lo em duas partes. Na metade superior voc deve reconhecer a nossa calculadora, onde
todos os sinais de controle foram ligados sada da unidade de controle (o bloquinho escrito
Ctrl), que fica na metade inferior do circuito.
Voc deve ainda reparar que a unidade de controle tambm tem uma sada ligada ao
barramento da calculadora; por esta sada que passam os operandos especificados nas
micro-instrues.
fornece tempos
para atualizaes: Sinais
t0: PC
t1: mIR
t2: Sinais ou Oper
Micro-instruo
corrente Operando
Figura 122: Unidade de controle da CPU-0
A Figura 122 mostra os detalhes internos da unidade de controle da CPU-0. Voc deve reparar
que a unidade de controle possui:
registradores de sinais e de operando, que armazenam os bits fornecidos pelas sadas
de mesmo nome;
um registrador mIR, que armazena a micro-instruo corrente;
um circuito de temporizao T, que j vimos na Figura 115, e que ao longo do tempo
fornece os sinais t0, t1 e t2 conforme mostrado na Figura 116.
atravs dos sinais fornecidos pelo circuito de temporizao que o ciclo de execuo de micro-
instrues implantado na CPU-0:
o sinal t0 atualiza o valor do PC;
o sinal t1 coloca no mIR a micro-instruo cujo endereo fornecido pelo PC;
o sinal t2 faz com que ou o registrador Sinais, ou o registrador Oper, copie sua
entrada, com a escolha dentre estes dois sendo determinada pelo bit 23 da micro-
instruo corrente.
Muito bem, j temos um circuito que executa programas formados por micro-instrues, onde
cada micro-instruo codifica sinais de controle ou operandos, sem necessidade de
interveno humana na execuo. Mas temos ainda que resolver dois problemas: como
construir um programa, e como fazer para colocar este programa na memria de micro-
instrues da CPU-0.
Micro-instruo
23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Efeito
Sinais
Compare_Clk
Da micro-
Operando?
Oper->Bus
ACC_Clear
Acumulado
RAM_Bus
ACC->Bus
Endereo
In->Dbus
MAR_Clk
RAM_Clk
Subtract
DR->Bus
ACC_Clk
Out_Clk
instruo
DR_Clk
In_Clk
0 1 ACC = 0
1 1 1 Oper = 1 Carrega no
2 1 Bus = Oper acumulador o
3 1 1 MAR = Bus contedo da posio 1
4 1 Bus = RAM da RAM
5 1 1 ACC = ACC + Bus
6 1 1 Oper = 2
7 1 Bus = Oper Soma ao acumulador
8 1 1 MAR = Bus o contedo da posio
9 1 Bus = RAM 2 da RAM
10 1 1 ACC = ACC + Bus
11 1 1 1 Oper = 3
12 1 Bus = Oper Armazena o contedo
13 1 1 MAR = Bus do acumulador na
14 1 Bus = ACC posio 3 da RAM
15 1 1 RAM = Bus
16
Figura 123: Construindo um programa para a CPU-0
Para programar a CPU-0 ns podemos usar uma tabela como a da Figura 123, cujas colunas se
dividem em 3 agrupamentos:
Endereo, que indica em qual posio da memria de programa a micro-instruo deve
ser armazenada,
Micro-instruo, onde so colocados pelo programador os 24 bits que compem a
micro-instruo propriamente dita (na figura ns no colocamos os zeros para no
poluir visualmente a tabela), e
Efeito, que contm informaes para consumo humano, indicando tanto o efeito de
cada micro-instruo como o efeito acumulado de grupos de micro-instrues.
O programa da Figura 123 corresponde exatamente aos sinais de controle e entradas de
operandos mostrados na Figura 112 e na Figura 113; sua execuo tem portanto o mesmo
efeito: somar os contedos das posies 1 e 2 da memria, e colocar o resultado na posio 3.
Construda a tabela-programa, os bits das micro-instrues devem ser armazenados em
alguma mdia, e carregados na memria de programa do processador. Nos computadores
atuais a carga de programas feita por um outro programa, chamado de carregador ou loader.
Sim, mas como que um loader vai parar na memria do computador? Nos computadores
atuais, um loader primitivo gravado pelo fabricante em uma memria ROM (Read Only
Memory), e executado no momento em que o computador ligado, constituindo a primeira
etapa de um procedimento que tem o nome de bootstrap. Usando um disco magntico
(tipicamente), o loader primitivo carrega um outro loader, mais sofisticado, que por sua vez
carrega outro mais sofisticado ainda, e isso termina com a carga do sistema operacional. O uso
normal de programas utiliza um loader do sistema operacional.
Nem sempre foi assim. Em computadores antigos e o autor destas linhas j chegou a utilizar
um deles o loader primitivo era carregado palavra por palavra, atravs do painel do
computador. Como voc pode ver na Figura 124, o painel continha uma srie de chaves cujo
posicionamento ligava ou desligava um bit, e botes para carregar o registrador de endereo
ou o contedo de uma posio de memria com os bits definidos pelas chaves. No era
necessrio fazer isso a cada vez que se ligava o computador: a memria principal daquele
tempo utilizava ncleos de ferrite, e no era voltil. Reservavam-se algumas posies de
memria para conter o loader, e a carga atravs do painel s era necessria quando, por um
erro de programao, algum escrevia sobre essas posies da memria.
Aqui ns no trabalhamos com memrias reais, e sim com memrias simuladas pelo Logisim.
Isso nos permite escrever diretamente valores para posies de memria, ou ler de um
arquivo um mapa da memria (para ter acesso a essas operaes, clique com o boto direito
do mouse sobre a memria). A Figura 125 mostra o formato de um arquivo com a codificao
em hexadecimal do programa da Figura 123 e a memria de programa Logisim aps a carga
deste arquivo. No site do curso voc ir encontrar planilhas que auxiliam na produo de
arquivos-programas em hexadecimal.
2.4.4 Desvios
Suponha agora que queremos construir para a CPU-0 um programa que some os contedos
das posies 1, 2, 3, 4 e 5 da memria principal, e coloque o resultado na posio 6.No
difcil: basta acrescentar ao programa mais passos de somas ao acumulador, como ilustra a
Figura 126.
Compare_Clk
Compare_Clk
Operando?
Operando?
Oper->Bus
Oper->Bus
ACC_Clear
ACC_Clear
RAM_Bus
ACC->Bus
RAM_Bus
ACC->Bus
In->Dbus
MAR_Clk
RAM_Clk
In->Dbus
MAR_Clk
RAM_Clk
Subtract
DR->Bus
Subtract
DR->Bus
ACC_Clk
ACC_Clk
Out_Clk
Out_Clk
DR_Clk
DR_Clk
In_Clk
In_Clk
1 1
1 1 1 1
1 1
1 1 1 1
1 1
1 1 1 1
1 1 1 1
1 1
1 1 1 1
1 1
1 1 1 1
1 1 1 1 1 1
1 1
1 1 1 1
1 1
1 1 1 1
1 1
1
1 1
1
1 1
1 1 1
1
1 1
1
1 1
1 1 1
1
1 1
1
1 1
Ns sabamos que era possvel realizar computaes arbitrariamente complicadas com a nossa
calculadora, aplicando manualmente sinais de controle, e entrando tambm manualmente
com os operandos necessrios. Com a CPU-0, ns mostramos que possvel automatizar
essas operaes, com o uso de uma unidade de controle impulsionada por um clock. Mas o
exemplo da soma de 5 parcelas nos mostra um problema: na CPU-0, um programa cresce de
tamanho com o nmero de operaes que realiza. Qual seria o tamanho de um programa que
soma um milho de parcelas?
Para conseguir escrever programas cujo tamanho no cresa com o nmero de operaes que
sua execuo realiza, precisamos alterar nosso modelo de execuo seqencial de micro-
instrues. Ns vamos agora apresentar um outro processador, a CPU-1, que possui uma
micro-instruo especial que desvia o fluxo de execuo para um endereo designado na
memria de programa. O ciclo de leitura e execuo de micro-instrues deve ser modificado
em funo disso, pois a prxima micro-instruo a ser executada nem sempre a que est
armazenada no endereo consecutivo da memria de programa.
23 22 21 2023 19 2218 21
17 16
20 15
19 14
18 13
17 12
16 11
15 10 Micro-instruo
14 913 812 711 610 59 48 37 26 15de
04 3 2 1 0
Sinais desvio
Sinais para a posio 1
na memria de programa
Compare_Clk
Compare_Clk
Oper->Dbus
Oper->Dbus
Operando?
Operando?
RAM_Dbus
RAM_Dbus
ACC->Dbus
ACC->Dbus
ACC_Clear
ACC_Clear
DR->Dbus
DR->Dbus
In->Dbus
In->Dbus
MAR_Clk
RAM_Clk
MAR_Clk
RAM_Clk
Subtract
Subtract
ACC_Clk
ACC_Clk
Out_Clk
Out_Clk
Desvio?
Desvio?
DR_Clk
DR_Clk
In_Clk
In_Clk
1 1
1 1 1 1
1 1
1 1 1 1
1 1 1 1
Figura 128: Unidade de controle da CPU-1, com destaque para a conexo do registrador de operando com o
contador de programa e para a deciso de desvio, indicada pelo bit 23 da micro-instruo corrente
A Figura 129 mostra o novo contador de programa, onde voc deve reparar que a entrada do
registrador de endereo est conectada sada de um multiplexador. Este multiplexador
encaminha para a entrada ou bem o valor corrente do PC acrescido de 1 (fornecido pela sada
do somador), quando a entrada Desvio igual a 0, ou ento o valor da entrada D, quando a
entrada Desvio igual a 1.
Micro-instruo
23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Efeito
Endereo
Sinais
Operando?
Desvio?
Compare_Clk
Oper->Dbus
da micro-
RAM_Dbus
ACC->Dbus
ACC_Clear
DR->Dbus
Acumulado
In->Dbus
MAR_Clk
RAM_Clk
Subtract
ACC_Clk
Out_Clk
instruo
DR_Clk
In_Clk
0 1 ACC=0
1 1 1 Oper=1
Carrega 1 no acumulador
2 1 Bus=Oper
3 1 1 ACC=ACC+Bus
4 1 1 Oper=1
5 1 Bus=Oper Soma 1 ao acumulador
6 1 1 ACC=ACC+Bus
7 1 1 PC=4 Desvia para 4
8
Na Figura 130 ns vemos uma tabela com um programa para a CPU-1, cujo efeito muito
simples: o programa usa o acumulador para contar 1, 2, 3, ... indefinidamente. Para executar
Compare_Clk
Oper->Dbus
Operando?
RAM_Dbus
ACC->Dbus
ACC_Clear
DR->Dbus
In->Dbus
MAR_Clk
RAM_Clk
Subtract
ACC_Clk
Out_Clk
Desvio?
DR_Clk
Menor
In_Clk
Maior
Igual
Desviar
1
para o
1endereo 4 se
1
Bus > ACC 1
1
1 1
1
1 1
1
1 1
1 1 1
Figura 131: Codificao de micro-instrues de desvio condicional
Na Figura 131 voc pode ver a codificao de micro-instrues que iremos adotar para um
novo processador, a CPU-2. Nessa codificao,
o bit 23 indica se a micro-instruo de desvio;
o bit 22, como na CPU-1, indica que a micro-instruo contm um operando;
os bits 21, 20 e 19 so usados nas micro-instrues de desvio, e especificam as
condie em que o desvio deve ser efetivamente realizado, em funo do valor
corrente do registrador de comparao. Se, por exemplo, tivermos uma micro-
instruo de desvio com os bits 21 e 20 iguais a 1, e o bit 19 igual a zero, na execuo
desta micro-instruo o desvio ocorrer somente se o registrador de comparao
estiver seja com a sada D<ACC ligada, seja com a sada D=ACC ligada. Um desvio
incondicional pode ser obtido colocando estes 3 bits iguais a 1.
Registrador
Compare
Unidade
de
Controle
Figura 132: Parte da CPU-1, destacando a alimentao da sada do registrador de comparao como entrada
adicional da unidade de controle
Na Figura 132 voc pode ver que a sada do registrador de comparao alimenta agora a
unidade de controle, fornecendo a informao necessria para as decises de desvio
condicional.
Lgica de Deciso:
Condies na micro-
instruo coincidem com
o status do registrador
de comparao?
Figura 133: A unidade de controle da CPU-2, com destaque para a lgica de desvio
23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Efeito
Sinais
Endereo
Operando?
Desvio?
Menor
Compare_Clk
Maior
Igual
Oper->Dbus
Da micro-
RAM_Dbus
ACC->Dbus
ACC_Clear
DR->Dbus
Acumulado
In->Dbus
MAR_Clk
RAM_Clk
Subtract
ACC_Clk
Out_Clk instruo
DR_Clk
In_Clk
0 1 In = Input
1 1 1 1 Oper=3
2 1 Bus=Oper Armazena a entrada Input na
3 1 1 MAR=Bus posio 3 da memria
4 1 Bus=In
5 1 1 RAM=Bus
6 1 ACC=0
7 1 1 Oper=1
Carrega 1 no acumulador
8 1 Bus=Oper
9 1 1 ACC=ACC+Bus
10 1 1 Oper=1
11 1 Bus=Oper Soma 1 ao acumulador
12 1 1 ACC=ACC+Bus
13 1 1 1 Oper=3
14 1 Bus=Oper Compara o contedo da
15 1 1 MAR=Bus posio 3 da memria com o
16 1 Bus=RAM acumulador
17 1 1 Compare=Bus::ACC
18 1 1 1 1 se D>ACC, PC=10 Desvia para 10 se D>ACC
19
Este programa inicia armazenando o valor encontrado na entrada Input (e que deve ser
colocado ali antes do incio da simulao) na posio 3 da memria. Em seguida acumulador
inicializado com o valor 1. Segue-se um loop de soma e de comparao, que inclui uma micro-
instruo de desvio condicional.
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
OpCode Mode Operand
Figura 135: Formato de uma instruo da CPU Pipoca
Mnemnico
OpCode10
OpCode2
Efeito
Desvia para a palavra apontada pelo operando efetivo se "D>ACC" = 1 JMPGT 6 0110
Desvia para a palavra apontada pelo operando efetivo se "D<ACC" = 1 JMPLT 7 0111
Carrega o operando efetivo no acumulador LOAD 8 1000
Espera OutEmpty = 1, e transfere o operando efetivo para o
OUTPUT
registrador Output; faz OutEmpty = 0 9 1001
Transfere o valor de ACC para a palavra apontada pelo operando
efetivo STORE 10 1010
Subtrai o operando efetivo de ACC, deixando o resultado em ACC SUB 11 1011
12 1100
13 1101
Estes cdigos podem ser usados para novas instrues
14 1110
15 1111
Figura 136: Instrues da CPU Pipoca
A Figura 136 mostra o conjunto completo de instrues da CPU Pipoca. Repare que a cada
instruo corresponde um cdigo de 4 bits (mostrado na coluna OpCode2) e um mnemnico
para o seu efeito. Repare tambm que, na descrio do efeito de cada instruo, ns fazemos
referncia a um operando efetivo, que o valor que resulta da aplicao do modo de
endereamento ao operando codificado na instruo. A idia que efeitos como
somar 2 ao acumulador ou
somar o contedo da posio 2 da memria ao acumulador ou ainda
somar o contedo da posio de memria cujo endereo o contedo da posio 2 de
memria ao acumulador
sejam obtidos pela mesma instruo, ADD, com modos de endereamentos diferentes para
cada caso. Nas trs possibilidades acima o operando codificado na instruo seria 2. Na
primeira possibilidade, o modo de endereamento codificado em bits seria 00, que chamamos
de modo imediato; na segunda, 01, ou modo direto, e na terceira, 10, ou modo indireto.
Nenhum ser humano com sade mental consegue construir um programa especificando bit a
bit suas instrues. O processo de programao da CPU-Pipoca consiste em preencher uma
tabela usando no os cdigos das instrues, mas seus mnemnicos, e tambm usando nomes
(labels) dados a posies de memria e no os endereos efetivos. Isso torna o programa
muito mais fcil de se escrever e se ler. Os bits de cada instruo so depois obtidos por uma
substituio cuidadosa dos mnemnicos e dos nomes de posies de memria por seus
cdigos em bits, em um processo que chamamos de montagem da instruo.
Instruction
Address10
Address16
Operand
Comentrios
Mode
Label
Size
Na Figura 137 ns vemos um exemplo de um programa escrito desta forma. Este programa
soma os contedos das posies de memria com endereos entre 15 e 19 (usando os nomes
os labels endereos entre X e XEND), e coloca o resultado na sada do processador. Vamos
explicar aos poucos alguns aspectos deste programa.
Instruction
Address10
Operand
Comentrios
Mode
Label
Size
Instrues
endereo P ao acumulador
1 6 STORE 0 SUM Coloca o resultado na posio SUM
1 7 LOAD 1 P Carrega o contedo de P
1 8 ADD 0 1 Soma 1
1 9 STORE 0 P Coloca o resultado em P
1 10 COMPARE 0 XEND Compara XEND com o acumulador
1 11 JMPLT 0 FINISH Se for menor, desvia para FINISH
1 12 JMP 0 LOOP Seno, volta para LOOP
FINISH 1 13 OUTPUT 1 SUM Coloca o resultado na sada
1 14 HALT Para.
X 1 15 3142
Dados
1 16 4542
1 17 3325 Nmeros a serem somados
1 18 1234
XEND 1 19 8786
SUM 1 20 0
P 1 21 0
Figura 138: Um programa descreve a ocupao da nica memria por instrues e por dados
A primeira coisa a ser percebida que o programa descreve tanto instrues como dados,
como mostra a Figura 138. A cada linha do programa corresponde uma palavra na memria a
no ser que a coluna Size seja usada para reservar mais de uma posio de uma vez.
No campo de instruo, o programador coloca o mnemnico, e no o cdigo binrio de cada
instruo. A coluna Label usada pelo programador para dar nomes a endereos de memria;
estes labels podem ser usados na coluna Operando do programa fonte, tornando muito mais
fcil modificar um programa quando se quer alterar a ocupao da memria. Na Figura 139 e
na Figura 140 voc pode ver em destaque dois exemplos do uso de labels no programa fonte.
Instruction
Address10
Address16
1 7 07 LOAD 1 P Carrega o contedo de P
Operand
1 8 08 ADD 0 1 Soma 1 Comentrios
Mode
Label
Size
1 9 09 STORE 0 P Coloca o resultado em P
1 10 0A
1 0 00 LOAD COMPARE 0
0 0 XEND Compara
Zera XEND com o acumulador
o acumulador
1 11 0B
1 1 01 STOREJMPLT 0 FINISH
0 SUM Se for menor,
Coloca 0 em SUMdesvia para FINISH
1 12 0C JMP
2 02 LOAD 0 LOOP
X Seno, volta para
Carrega o endereo LOOP
X no acumulador
FINISH 1 13 3 0D OUTPUT
03 STORE 01 PSUM resultado Xnaem
Coloca o endereo sada
P
LOOP 1 14 4 04 0E LOAD
HALT 1 SUM Para. o contedo de SUM no acumulador
Carrega
X 1 15 0F 3142 Soma o contedo da posio de memria cujo
11 16
5 05 10 ADD 2 P4542
endereo P ao acumulador
1 17 11
6 06 STORE 3325
0 SUM Nmeros
Coloca o resultado naaposio
serem somados
SUM
1 18 12
7 07 LOAD 1 P 1234 Carrega o contedo de P
XEND 1 19 8 08 13 ADD 0 18786 Soma 1
SUM 1 20 9 09 14 STORE 0 P0 Coloca o resultado em P
P 1 1021 0A 15 COMPARE 0 XEND 0 Compara XEND com o acumulador
1 Figura
11 0B 139:JMPLT
Um exemplo 0de uso
FINISH Se for
de labels menor,
como desvia no
operandos para FINISH
cdigo fonte
1 12 0C JMP 0 LOOP Seno, volta para LOOP
FINISH 1 13 0D OUTPUT 1 SUM Coloca o resultado na sada
1 14 0E HALT Para.
Instruction
Address10
Address16
X 1 15 0F 3142
Operand
1 16 10 4542 Comentrios
Mode
Label
Size
Cada instruo no programa fonte deve ser codificada em bits para se ter uma imagem da
memria gravada em alguma mdia, que ser carregada na memria do processador para a
execuo do programa. Na Figura 141 voc pode ver um exemplo deste procedimento de
codificao em bits, que chamado de montagem da instruo.
Figura 142: Fac-smile do relatrio de especificao da linguagem FORTRAN, obtido na referncia (McJones)
Nationale des Ponts et Chausses, duas instituies francesas. muito semelhante ao Matlab
e, fator essencial para sua escolha, gratuito. O Scilab tambm um interpretador, e
encontra-se atualmente na verso 5.1, lanada em fevereiro de 2009.
Do ponto de vista da cincia da computao, Matlab e Scilab no mereceriam destaque em
uma galeria de linguagens de programao. Entretanto, a facilidade que oferecem para a
construo de pequenos programas voltados para engenharia e cincia no encontra rival nas
linguagens tradicionais como Fortran, C ou Java.
Antes de entrarmos na apresentao do ambiente e da linguagem Scilab queremos colocar
algumas observaes gerais sobre linguagens de programao, que voc deve ter em mente
ao iniciar seu estudo. Uma linguagem de programao, como as linguagens naturais, une
riqueza de expresso a detalhes sintticos e algumas arbitrariedades. Detalhes e
arbitrariedades frequentemente vm de escolhas feitas no passado, incluindo algumas que j
no fazem mais sentido mas que so mantidas por uma inrcia natural. Seu aprendizado exige
uma postura paciente, pois envolve no incio uma taxa relativamente alta de memorizao.
Mas como uma linguagem natural, a fluncia vem com o uso, e com a fluncia vem a
percepo da riqueza da linguagem.
O Scilab tambm um ambiente que interpreta comandos e programas. Ele oferece uma
console para interao com o usurio, um editor para a construo de programas, o Scipad, e
tambm emite mensagens de erros relativos tanto obedincia de comandos e programas s
regras da linguagem como a problemas que podem ocorrer na execuo, como uma diviso
por zero.
Barra de
Menus
Barra de
Ferramentas
Prompt de
Comandos
Figura 143: cone e tela inicial com a console do Scilab
A Figura 143 mostra a tela obtida ao clicar sobre o cone do Scilab. uma janela simples, com
uma barra de menus e uma barra de ferramentas, e um painel central com um prompt de
comandos, indicado pela setinha --> . nesse prompt que so digitados comandos a serem
interpretados pelo Scilab. Esta janela a console do Scilab.
Prompt de
-->a = 10 O Scilab ecoa o
Comandos
a = valor recebido pela
varivel
a uma varivel 10.
que passa a existir, -->b = 2^10
recebe e guarda um b =
valor (10, no caso) 1024. Exponenciao
-->c = a+b
c = O valor recebido
1034. pode ser uma
expresso aritmtica
com variveis j
conhecidas
Figura 144: Variveis e comandos de atribuio
-->d = a+x
!--error 4
Undefined variable:
x
Conforme ilustrado na Figura 145, todas as variveis envolvidas na <expresso> devem ter
valores definidos no momento da execuo do comando.
Vale ainda observar que a <expresso> pode conter a <varivel alvo>, em um arranjo similar
ao utilizado nos registradores acumuladores.
-->a = %pi
a = Valor pr-
definido
3.1415927
; suprime
o eco
-->b = 2*%pi;
automtico
O Scilab oferece tambm variveis com valores pr-definidos, como %pi ou %eps, e uma
enorme variedade de funes pr-definidas (veja a Figura 147). Valores numricos so
representados no Scilab em ponto flutuante de 64 bits; %pi a melhor aproximao de
nessa representao, e o mesmo vale para %eps e outras constantes.
Um detalhe muito til a possibilidade de supresso do eco automtico, que algumas vezes
polui a tela com informao desnecessria, e que obtido com o uso de um ; colocado aps
o comando de atribuio.
Na Figura 148 ns vemos alguns exemplos de como o Scilab interpreta expresses aritmticas.
De uma forma geral, recomendvel o uso de parnteses para tornar clara a inteno do
programador.
Repare que usamos variveis delta, r1 e r2, com nomes aceitveis para o Scilab e com
significado para ns. Repare tambm nas expresses usadas nos comandos de atribuio.
Erros comuns cometidos por iniciantes so:
escrever delta = b^2 4ac, omitindo os operadores de multiplicao, que
entretanto so imprescindveis para que o Scilab compreenda a expresso, ou
escrever r1 = (-b+sqrt(delta))/2*a, o que na verdade levaria ao clculo de
, o que no o que queremos.
Muito bem, conseguimos usar o Scilab para resolver uma equao de 2 grau, o que no chega
a ser uma faanha. Mas tivemos ganhos com relao execuo dos mesmos clculos com
uma calculadora de mo:
o uso de variveis evita re-digitaes e possveis erros;
resultados intermedirios so memorizados e podem ser reaproveitados;
o uso de frmulas como na Figura 150 aumenta muito a confiana nos clculos.
As limitaes do uso direto da console Scilab para clculos tornam-se claras quando queremos
resolver outra equao de 2 grau. Frmulas tm que ser re-digitadas, abrindo uma ocasio
para erros, com pouco aproveitamento do trabalho j feito. A soluo para isso usar o Scilab
como um interpretador de programas.
Um programa fonte Scilab um arquivo ASCII, isto , um arquivo que s contm textos sem
formatao, e que tem a terminao .sce. Um arquivo-programa contm comandos Scilab, e
construdo usando o editor SciPad (veja na Figura 152 como o editor aberto no Scilab 5.1).
A execuo (interpretao) de um programa se faz seguindo o menu File/Execute da console
do Scilab; essa execuo equivale digitao na console dos comandos presentes no arquivo.
Ateno: nunca use o Word ou qualquer outro editor de textos sofisticado para abrir e/ou
editar arquivos de programas. Esses editores podem introduzir bytes de informao de
formatao, o que perturba completamente a interpretao do programa pelo Scilab.
No editor Scipad voc pode:
Criar um novo programa, atravs do menu File/New;
Abrir para edio um programa j existente, atravs do menu File/Open
Editar um programa
Salvar o programa editado, atravs do menu File/Save
Executar um programa, atravs do menu Execute/Load into Scilab
e vrias outras coisas que voc ir aprendendo aos poucos.
O Scilab trabalha com um diretrio corrente, que a primeira opo de localizao para
procurar e para salvar arquivos. Na console do Scilab voc pode escolher o diretrio corrente
atravs do menu File/Change current directory. O diretrio corrente do Scipad o diretrio
corrente do Scilab no momento em que o editor aberto.
Um conselho: organize os seus arquivos! Perde-se muito tempo procurando arquivos gravados
no se lembra aonde. O autor destas linhas cria um diretrio para cada semana, onde so
colocados todos os arquivos que so utilizados; voc pode adotar uma organizao similar em
seu computador pessoal. Ao usar computadores compartilhados, crie um diretrio de trabalho
com o seu nome, o que ir facilitar a sua limpeza posterior.
// indica que a
linha um
comentrio
A Figura 153 mostra um programa que tem em cada linha exatamente os mesmos comandos
que utilizamos na console para resolver a equao de 2 grau. Ns demos a este programa o
nome Eq2g1.sce; usamos um nmero no nome do arquivo porque faremos outras verses
deste mesmo programa. Se voc rodar este programa, usando o menu File/Execute, voc
obter os mesmos resultados que conseguimos com a console.
As duas primeiras linhas do programa Eq2g1.sce se iniciam por //, o que faz com que sejam
ignoradas pelo Scilab no momento da execuo. Essas linhas so comentrios, e tm o
importantssimo objetivo de melhorar a compreenso de um programa por um leitor humano.
Com um programa gravado em um arquivo, se quisermos resolver uma nova equao, bastar
substituir no programa os valores dos novos coeficientes e execut-lo novamente.
Comparando com o processo de resoluo via console, o uso de um programa reduz
consideravelmente as chances de erros de digitao.
Entretanto, a prtica de se alterar programas para introduzir dados que se modificam a cada
execuo no recomendvel, e nem exeqvel quando o volume de dados muito grande. O
melhor a fazer modificar o programa para permitir que o usurio defina os valores dos
coeficientes a cada execuo.
O comando input permite essa interao com o usurio. Como vemos na Figura 154, este
comando recebe como parmetro uma frase a ser exibida para o usurio, que normalmente
usada para descrever o valor a ser digitado.
A Figura 155 mostra a console do Scilab em uma execuo do programa Eq2g2.sce, onde voc
pode verificar o efeito da execuo dos comandos input. Os valores digitados pelo usurio
A Figura 156 mostra o programa Eq2g3.sce, que atende a essas especificaes. Este programa
introduz dois novos comandos: if, e printf. Repare que no estamos usando ; aps
vrios dos comandos de atribuio, o que suprime o eco automtico e torna a sada mais
limpa.
if <condio> then
<bloco ento>
else
<bloco seno>
end
Figura 157: O comando if
if <condio> then
<bloco ento> if <condio> then
else <bloco ento>
// Nenhum comando aqui end
end
Figura 158: Duas formas equivalentes do comando if, a da direita sem a clusula else
<condio>
<bloco ento>
<bloco seno>
Figura 159 :Partes do comando if do programa Eq2g3.sce
Expresses lgicas normalmente fazem uso de operadores relacionais para comparar valores
de duas expresses. A Tabela 13 mostra os operadores relacionais usados no Scilab, onde
voc pode reparar que igual a representado por dois = consecutivos, uma herana da
linguagem C, e que existem duas formas de representao de diferente de.
Tabela 13: Operadores relacionais
<frase> a sentena que se quer imprimir na tela, e que pode estar entremeada
por cdigos de formato como %g; %g um cdigo de formato geral para expresses
com valores numricos (ns veremos em seguida expresses com outros tipos de
valores); existem vrios outros cdigos de formato como %d, %f ou %s, que iremos
explorar em exerccios e em outros exemplos neste texto.
<lista de expresses> uma lista de expresses separadas por vrgulas, que
so calculadas no momento da execuo do comando;
as expresses na lista so mapeadas uma a uma nos cdigos de formato, na mesma
sequncia em que aparecem na <frase>, e a sentena impressa obtida pela
substituio do valor da expresso na posio marcada pelo cdigo de formato.
No comando printf("As razes so %g e %g",r1,r2)as duas expresses na lista
so muito simples, formadas por uma varivel. A expresso r1 mapeada no primeiro %g, e a
expresso r2 mapeada no segundo %g. A Figura 160 mostra uma sada do programa
Eq2g3.sce onde se pode ver o efeito da execuo deste comando.
// Clculo do fatorial de n
// Leitura de n
n = input("Valor de n = ");
// Clculo do fatorial
fat = 1;
for i=1:n
fat = fat*i;
end
// Impresso do resultado
printf("O fatorial de %d %d",n,fat);
Figura 161: Programa Fatorial1.sce
Mas a parte central do programa o loop destacado em vermelho na figura. A varivel fat
inicializada com o valor 1. Na primeira passagem pelo loop, i igual a 1, e fat recebe o
valor 1*1. Na segunda passagem i igual a 2, e fat recebe o valor 1*2, igual a 2; na terceira
passagem, fat recebe o valor 2*3, igual a 6; na quarta passagem, o valor 6*4, igual a 24; na
quinta, 24*5, e assim por diante. Ou seja, pelo fato de a cada passagem a varivel fat receber
como valor seu valor anterior multiplicado por i, na i-sima execuo do corpo do for, fat
passa a conter o fatorial de i. Como o loop termina com i igual a n, o valor de fat na sada
do loop o fatorial de n.
Tabela 14: Tabela de Senos
x seno(x)
0.0 0.0000
0.2 0.1987
0.4 0.3894
0.6 0.5646
0.8 0.8415
Vamos agora usar o comando for para a construo de uma tabela como a Tabela 14, com x
variando de 0 a , de 0.2 em 0.2. Antes porm vamos aprender mais sobre o comando for,
cuja forma geral est mostrada na Figura 162
for i = 1:2:10
printf('\ni = %g',i);
end
i = 1
i varia de 2 em 2
i = 3
i = 5 Sada
i = 7
Repare que i no assumiu o
i = 9 limite superior do loop
Figura 163: Exemplo de comando for com passo diferente de 1
for i = 20:-2:16
printf('\ni = %g',i);
end
i = 20 Sada
i = 18
i = 16
Figura 164: Exemplo de for com passo negativo
O <passo> de um for pode ser negativo, como mostrado na Figura 164, e a varivel de
controle pode assumir valores no inteiros, como na Figura 165.
A varivel de controle
pode assumir valores
no inteiros
for x = 0:0.3:0.7
printf('\nx = %g',x);
end
x = 0
Sada
x = 0.3
x = 0.6
Figura 165: Exemplo de for com a varivel de controle assumindo valores no inteiros
O programa da Figura 166 parece atender especificao, mas quando executado pelo Scilab
produz uma sada de difcil compreenso, como mostrado na Figura 167.
-->
0 00.2 0.1986690.4 0.3894180.6 0.5646420.8 0.7173561 0.841471
Figura 167: Primeiros caracteres da sada do programa Tabela_de_Senos_1.sce
Um primeiro problema a corrigir a separao em linhas, o que pode ser obtido usando o
smbolo \n na frase do comando printf. Com isso ns chegamos ao programa
Tabela_de_Senos_2.sce, mostrado na Figura 168.
0 0
0.2 0.198669
0.4 0.389418
0.6 0.564642
0.8 0.717356
1 0.841471
1.2 0.932039
Figura 169: Sada do programa Tabela_de_Senos_2.sce
// Impresso do cabealho
printf("\n x seno(x)")
x seno(x)
0.0 0.0000
0.2 0.1987
0.4 0.3894
0.6 0.5646
0.8 0.7174
1.0 0.8415
1.2 0.9320
Figura 171: Primeiras linhas da sada do programa Tabela_de_Senos_3.sce
while <condio>
<bloco while>
end
Figura 172: O comando while
Nesse comando:
<condio> uma expresso lgica; o loop s termina quando essa expresso for
avaliada para falso.
<bloco while> um bloco de comandos.
Todo comando for pode ser substitudo por um comando while; a Figura 173 mostra um
exemplo dessa substituio.
x = 0;
for x = 0:0.2:2*%pi while x <= 2*%pi
printf("\n%3.1f %7.4f",... printf("\n%3.1f %7.4f",...
x, sin(x)) x, sin(x))
end x = x+0.2;
end
Figura 173: Mesmo loop obtido com comandos for e while
O emprego do comando while deve ser feito com ateno, pois voc pode prescrever um
loop que nunca ir parar, como no exemplo da Figura 174. O while s ser interrompido
quando x for maior que 10, o que nunca acontecer porque x vale 0 inicialmente, e a cada
passo, fica ainda menor.
x = 0;
while x <= 10
printf("\nx = %g", x)
x = x - 0.2;
end
Figura 174: Um loop infinito
ou
m = input("a = ");
n = input("b = ");
a = m;
b = n;
while a <> b
if a > b then
a = a-b;
else
b = b-a;
end
end
printf("mdc(%d,%d) = %d",m,n,a)
Figura 175: Programa para clculo do mximo divisor comum pelo algoritmo de Euclides
-->a = 7>5
a =
T
-->b = 3 ~= 10-7
b =
F
-->c = 3 == 10-7
c =
T
Figura 176: Atribuico de valores lgicos a variveis na console do Scilab
Variveis com valores lgicos podem ser parte de expresses lgicas, que usam os operadores
lgicos ~ (NOT), & (AND) e | (OR), definidos, como voc pode esperar, exatamente como na
Tabela 9 (pgina 29).
-->a = %t; b = %f;
-->~a
ans =
F
-->a & b
ans =
F
-->a | b
ans =
T
Figura 177: Exemplos de uso dos operadores lgicos ~ (not), & (and) e | (or) na console do Scilab
Alm de valores lgicos, variveis Scilab podem armazenar dados no numricos. Na Figura
178 ns vemos exemplos de como atribuir sequncias de caracteres o termo usado em
ingls, strings a variveis.
-->a = "Programao"
a =
Programao
-->b = " de '
Aspas simples (') e duplas
b = (") so equivalentes
de
-->c = "Computadores"
c =
Computadores
Figura 178: Atribuindo strings a variveis
Strings so escritos entre aspas, simples ou duplas. Voc pode mesmo iniciar um string com
aspas duplas e termin-lo com aspas simples.
Para strings, + significa
concatenao
-->a = 'Programao';
-->b = ' de ';
-->c = 'Computadores';
-->Disciplina = a + b + c
Disciplina =
Programao de Computadores
Figura 179: Concatenao de strings
Uma operao comum com strings a concatenao, que consiste na justaposio de dois
strings. No Scilab a concatenao utiliza o mesmo smbolo da adio numrica, o +.
Fim do string?
-->x = 'String "com aspas"'
!--error 276
Missing operator, comma, or semicolon
Aspas so usadas para marcar o incio e o fim de strings, e isto pode provocar um problema ao
se tentar representar strings que contm aspas, como mostrado na Figura 180. Para isso, basta
colocar duas aspas consecutivas na posio desejada, como na Figura 181.
-->2*'3.1415926'
!error 144
Undefiled operation for the given operands
Figura 182: Strings formados por algarismos no so nmeros para o Scilab
Strings tambm podem ser lidos pelo comando input, como no exemplo Nome =
input("Seu nome, por favor"). Escrevendo dessa forma o comando input o
usurio deve digitar o string entre aspas. possvel eliminar a necessidade de escrita do string
entre aspas usando o comando input com um parmetro extra, um string com o valor
"string", como no comando input("Seu nome, por favor","string").
Dois exemplos de execues deste programa esto na Figura 185. Neste programa
importante observar:
A frase utilizada no comando input para a varivel Pontos o resultado de uma
operao de concatenao (+);
Os comandos printf utilizam o cdigo de converso %s, apropriado para strings.
Estes dois truques so exemplos de manipulao de strings que podem tornar mais simptica a
interao de um programa com seu usurio.
Um programa como o Eq2g3.sce ( Figura 156) , que resolve uma nica equao de 2 grau a
cada execuo, se torna mais til se passar a resolver tantas equaes quantas o usurio
queira. Uma estrutura simples para esta repetio controlada pelo usurio pode ser obtida
usando uma varivel lgica para controlar um loop while, conforme o modelo mostrado na
Figura 186.
continua = %t;
while continua
// Processamento de um item
printf("Item processado")
A cada passagem do loop, o usurio interrogado sobre o seu desejo de continuar, o que ele
pode expressar entrando com o caractere s, de sim. Se ele entrar com o caractere n (na
verdade, com qualquer string diferente de s), o loop interrompido e o programa termina.
A Figura 187 mostra o programa Eq2g4.sce, que resulta da aplicao deste padro sobre o
programa Eq2g3.sce. O menu Edit/Indent Selection do editor Scipad muito til para indentar
um bloco de comandos selecionados.
Pontos Conceito
A
B
C
D
E
F
// Determinao do conceito
if Pontos >= 90 then
Conceito = "A";
else
if Pontos >= 80 then
Conceito = "B";
else
if Pontos >= 70 then
Conceito = "C";
else
if Pontos >= 60 then
Conceito = "D";
else
if Pontos >= 40 then
Conceito = "E"
else
Conceito = "F"
end
end
end
end
end
printf("%s, com %g pontos voc obteve o conceito %s!",...
Nome, Pontos, Conceito)
Figura 188: O programa PontosConceito.sce
Como j dissemos e continuaremos a dizer ao longo desse curso, programas so feitos para
serem executados por computadores, mas tambm para serem lidos por humanos. Ao fazer
um programa voc deve se preocupar com a sua legibilidade, tanto por outras pessoas que
venham a trabalhar com ele, como com voc mesmo, algum tempo depois de t-lo escrito.
Vamos agora desenvolver um programa que produza uma tabuada de multiplicao, como
mostrado na Figura 191.
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
Figura 191: Tabuada de Multiplicao
Um problema como este se resolve com dois for aninhados: um externo, para as linhas, e um
interno, para as colunas de cada linha, o que feito pelo programa Tabuada1.sce, mostrado na
Figura 192.
// Tabuada de multiplicao
for linha = 1:9
for coluna = 1:9
printf("%g",linha*coluna);
end
end
Figura 192: O programa Tabuada1.sce
Ao executar este programa verificamos entretanto que sua sada est ininteligvel:
12345678924681012141618369121518212...
formando uma longa sequncia de algarismos sem separao, todos em uma nica linha. O
que houve? Esquecemos de orientar o Scilab para mudar de linha, e tambm para, dentro de
cada linha, separar cada coluna.
// Tabuada de multiplicao
for linha = 1:9
for coluna = 1:9
printf("%3g",linha*coluna);
end
printf("\n");
end
Figura 193: O programa Tabuada2.sce
3.1.7 Arquivos
Arquivos so unidades de armazenamento de dados no-volteis, que sistemas operacionais
como Windows ou Linux permitem que sejam recuperados pelo nome e pela posio em uma
organizao hierrquica de diretrios. Um arquivo criado por um programa, e pode ser lido e
modificado por outros programas, programas que muitas vezes so executados em outros
computadores.
Existem muitos tipos de arquivos que podem ser manipulados por programas Scilab, mas neste
curso iremos aprender somente a trabalhar com arquivos ASCII, isto , arquivos que
normalmente so legveis por humanos, e que podem ser editados usando programas como o
Bloco de Notas do Windows.
Comandos bsicos para uso de arquivos no Scilab so:
uigetfile, que permite ao usurio selecionar um arquivo navegando nos diretrios
do sistema operacional;
mopen e mclose ,necessrios para iniciar e para terminar a manipulao de um
arquivo por um programa Scilab;
mfscanf e mfprintf , usados para ler e para gravar valores de variveis em
arquivos abertos;
meof , que permite testar se o fim de um arquivo (eof vem de end of file) j foi
atingido.
A Figura 194 mostra a janela de navegao para escolha de um arquivo aberta no Windows
Vista aps a execuo de um comando uigetfile.
O comando uigetfile retorna um string com a rota completa isto , desde o diretrio raiz
do arquivo escolhido. Isso pode resultar em strings longos como o atribudo varivel f na
Figura 195.
O string obtido pode ser usado para abrir (com mopen) o arquivo correspondente. O nome de
arquivo escolhido pode ser novo ou j existir no sistema de arquivos do operacional.
Outras formas de uso do comando uigetfile so:
Arq = uigetfile()
o Mais simples, sem ttulo na janela de escolha do arquivo;
Arq = uigetfile("*.txt",pwd(),"Escolha um arquivo")
da = mopen(NomeCompletoDoArquivo, r)
Descritor do
arquivo obtido
por mopen
Figura 197: O comando mfscanf
A leitura de dados em um arquivo feita pelo comando mfscanf, cuja forma est mostrada
na Figura 197. A cada execuo so lidos dados em uma linha do arquivo. Como um exemplo
de sua utilizao, considere o comando
[n,a,b,c] = mfscanf(da,"%g %g %g")
aplicado a um arquivo com os dados mostrados abaixo.
8 32 -40
7 -21 14
5 25 0
7 -63 0
Descritor do
arquivo obtido
por mopen
Figura 198: O comando mfprintf
O comando mfprintf bastante similar ao nosso conhecido printf, mas, por ser aplicado
a arquivos, exige como parmetro extra um descritor de arquivo aberto, como mostrado na
Figura 198.
Para ilustrar o uso de arquivos vamos retornar s equaes de 2 grau, mas agora vamos obter
os coeficientes das equaes em um arquivo de entrada, onde cada linha contm os
coeficientes de uma equao. Um possvel arquivo de entrada seria o coefs2g.txt, que pode ser
examinado com o Bloco de Notas, e cujas primeiras linhas esto mostradas na Figura 199.
Nosso programa deve ler o arquivo de entrada e, para cada linha lida, gravar uma linha em um
arquivo de sada contendo os coeficientes lidos e as razes calculadas. Isso deve ser feito
somente para as equaes com razes reais; linhas de entrada que formem equaes com
razes complexas devem ser ignoradas.
A Figura 200 mostra o programa Eq2g5.sce que atende a esta especificao. Neste programa
voc deve reparar que:
A localizao dos arquivos de entrada e sada feita com a verso do comando
uigetfile, que facilita a navegao na rvore de diretrios para o usurio;
Os arquivos de entrada e de sada so abertos no incio do programa e fechados no
fim;
O loop while controlado pela funo ~meof(daE) que testa se o fim do arquivo
de entrada foi encontrado. Seria possvel usar por exemplo o Bloco de Notas para
descobrir o nmero de linhas do arquivo de entrada, e controlar o loop por um
comando for, mas esta no uma boa prtica, pois o programa deveria ser alterado
para cada tamanho de arquivo de entrada.
3.2 Matrizes
Matrizes no Scilab so variveis que contm um nmero potencialmente grande de valores.
na manipulao de matrizes que o Scilab (seguindo o Matlab) mostra uma grande
superioridade sobre linguagens como C ou Fortran.
-->A = [1 2 3; 4 5 6]
A =
1. 2. 3.
4. 5. 6.
Figura 201: Atribuindo uma matriz a uma varivel
A Figura 201 mostra uma maneira simples de se criar uma matriz atravs de um comando de
atribuio na console do Scilab. Os elementos da matriz so dispostos entre colchetes. Espaos
(poderiam ser vrgulas) separam elementos, e ; separam linhas.
-->A = [1 2 3; 4 5 6]
A =
1. 2. 3.
4. 5. 6.
-->e = A(2,3)
e =
6.
Figura 202: Obtendo o valor de um elemento de uma matriz
A(2,3) , por exemplo, refere-se ao elemento na segunda linha e na terceira coluna; A(1,2)
o elemento na primeira linha e na segunda coluna.
-->A(1,2) = 33
A =
1. 33. 3.
4. 5. 6.
O Scilab to orientado para matrizes que todas as variveis Scilab so matrizes. As variveis
simples com que temos trabalhado so, na verdade, matrizes com uma nica linha e uma
nica coluna. possvel perceber isso usando o comando [nl,nc] = size(A) para obter
as dimenses de uma matriz A . Essa funo retorna dois parmetros, o nmero de linhas e o
nmero de colunas da matriz. A Figura 204 mostra dois exemplos de uso da funo size.
-->A = [1 2 3; 4 5 6];
-->[nl,nc] = size(A)
nc =
3.
nl =
2.
-->k = 0;
-->[L,C] = size(k)
C =
1.
L =
1.
Figura 204: Matrizes e a funo size
Uma matriz cresce quando atribumos valores a elementos com ndices superiores aos
ndices j referenciados. Por exemplo, quando fazemos x = 7 estamos criando uma matriz 1
x 1; se em seguida fizermos x(2,3) = 13, a matriz x assume as dimenses 2 x 3, e os
elementos no referenciados recebem o valor zero, como mostrado na Figura 205.
-->x(2:4,3:5) = -1
x =
Se x uma matriz 7x5, x(2:4,3:5) denota a parte da matriz compreendida pela interseo
das linhas de 2 a 4 e das colunas de 3 a 5, como mostrado na Figura 207.
x =
40. 58. 38. 73. 53. 4. 58.
87. 68. 92. 26. 11. 67. 48.
11. 89. 94. 49. 22. 20. 22.
19. 50. 34. 26. 62. 39. 84.
56. 34. 37. 52. 76. 83. 12.
x =
-->a = x(2,:)
a =
Ao se referenciar a uma parte de uma matriz que contm, seja todas as linhas, seja todas as
colunas, possvel usar uma notao simplificada com :. A Figura 209 mostra um exemplo
de uso desta notao para obter todos os elementos em uma linha de uma matriz.
x =
91. 28. 68. 40. 58. 38. 73.
4. 12. 15. 87. 68. 92. 26.
48. 77. 69. 11. 89. 94. 49.
26. 21. 84. 19. 50. 34. 26.
41. 11. 40. 56. 34. 37. 52.
-->b = x(:,3:5)
b =
68. 40. 58.
15. 87. 68.
69. 11. 89.
84. 19. 50.
40. 56. 34.
Figura 210: Obtendo os elementos de todas as linhas nas colunas de 3 a 5
Outro exemplo est mostrado na Figura 210, onde x(:,3:5) designa a parte de x formada
pelos elementos em todas as linhas e nas colunas de 3 a 5.
-->x = [1 2 3; 4 5 6];
-->y = [10 20 30; 40 50 60];
-->x + y
ans =
11. 22. 33.
44. 55. 66.
-->x - y
ans =
- 9. - 18. - 27.
- 36. - 45. - 54.
Figura 211: Adio e subtrao de matrizes
A Figura 211 mostra exemplos de adio e subtrao de matrizes. Com estas operaes so
sempre feitas elemento a elemento, os operadores .+ e .- no so necessrios, e no
existem no Scilab.
-->x = [1 2 3; 4 5 6]
x =
1. 2. 3.
4. 5. 6.
-->y = [10 20; 30 40; 50 60]
y =
10. 20.
30. 40.
220 = 1x10 + 2x30 + 3x50
50. 60.
-->x * y
ans =
220. 280.
490. 640.
Figura 212: Exemplo de produto matricial
Na Figura 212 ns vemos um exemplo do produto matricial de duas matrizes, obtido com o
operador *, e que segue a frmula da lgebra linear para o produto de uma matriz de
dimenses por uma matriz de dimenses , resultando em uma matriz ,
onde .
-->x = [1 2; 3 4];
-->y = [10 20; 30 40];
-->x * y
ans = Produto
Matricial
70. 100.
150. 220.
-->x .* y
ans = Produto Elemento a
10. 40. Elemento
90. 160.
Figura 213: Produto matricial (*) versus produto elemento a elemento (.*) de duas matrizes
O Scilab emite uma mensagem de erro quando ocorre uma tentativa de multiplicao de
matrizes com dimenses incompatveis com a operao. A Figura 213 mostra a diferena entre
as operaes de produto matricial e produto elemento a elemento.
-->x = [1 2 3; 4 5 6];
-->x * 2
ans =
2. 4. 6.
8. 10. 12.
-->x .* 2
ans =
2. 4. 6.
8. 10. 12.
Figura 214: Multiplicando uma matriz por um escalar
Uma matriz pode ser multiplicada por um escalar, caso em que os operadores * e .* so
equivalentes, como mostrado na Figura 214.
-->x = [1 2; 3 4];
-->x^2
ans = Produto
7. 10. Matricial x*x
15. 22.
-->x .^ 2
ans =
Exponenciao
1. 4. Elemento a
9. 16. Elemento
Figura 215: Exponenciao matricial (^) versus exponenciao elemento a elemento (.^)
Quanto exponenciao, o Scilab interpreta x^3 como x*x*x , ou seja como o produto
matricial triplo da matriz x por ela mesma. o que s faz sentido quando x uma matriz
quadrada. J x .^ 3 interpretado como x .* x .* x, ou seja, o produto triplo da
matriz x por ela mesma, feito elemento a elemento, operao que pode ser feita com
matrizes de dimenses arbitrrias. A Figura 215 mostra um exemplo da diferena entre as duas
operaes.
-->a = [1 2 3; 4 5 6]
a =
1. 2. 3.
4. 5. 6.
-->a'
ans =
1. 4.
2. 5.
3. 6.
Figura 216: Transpondo uma matriz
A =
4. 7. 6.
2. 2. 1.
1. 1. 6.
-->IA = inv(A)
IA =
- 0.3333333 1.0909091 0.1515152
0.3333333 - 0.5454545 - 0.2424242
0. - 0.0909091 0.1818182
Figura 217: A funo inv, que produz a matriz inversa
A funo inv produz a matriz inversa da matriz dada como argumento. A Figura 217 mostra
um exemplo de sua utilizao. Quando multiplicamos uma matriz por sua inversa esperamos
obter a matriz identidade, mas no bem isso o que mostra a Figura 218.
-->A * IA
ans =
1. 0. - 4.441D-16
1.110D-16 1. - 1.110D-16
5.551D-17 0. 1.
-->IA * A
ans =
1. 8.327D-17 0.
0. 1. 0.
0. 0. 1.
Figura 218: O produto de uma matriz por sua inversa ligeiramente diferente da matriz identidade
Ali vemos elementos no nulos fora da diagonal principal tanto de A * IA como de IA *A.
Isso mais uma manifestao dos erros de arredondamento que ocorrem em operaes
aritmticas de ponto flutuante. No caso, esses erros no so motivo de preocupao, pois os
elementos no nulos fora da diagonal tm valor absoluto ordens de grandeza menores que os
elementos das matrizes.
Podemos usar a inversa de uma matriz para resolver um sistema de equaes lineares
Usando a console do Scilab, o sistema pode ser resolvido com a seqncia de operaes
mostrada na Figura 219.
-->b = [-4 0 1]
b =
- 4.
0.
1.
-->x = inv(a)*b
x =
- 0.5
2.
- 1.
Figura 219: Resolvendo um sistema de equaes lineares
A preciso do resultado pode ser avaliada calculando , o que pode ser feito no Scilab
como mostrado na Figura 220.
-->residuo = a*x - b
residuo =
0.
- 2.220D-16
0.
Figura 220: Calculando o erro numrico da soluo encontrada
-->x = 10:13
x =
10. 11. 12. 13.
-->x = 12:-0.5:10
x =
12. 11.5 11. 10.5 10.
Figura 221: Construo de vetores regulares
Uma outra forma de se conseguir vetores com valores regularmente espaados com o uso da
funo linspace(<valor inicial>, <valor final>, <nmero de
pontos>), onde, alm do valor inicial e do valor final, fornecido o nmero de pontos em
que se deseja dividir o intervalo, ao invs do valor do passo. A Figura 222 mostra dois
exemplos de uso da funo linspace.
Nro. de Pontos
-->x = linspace(0,10,3)
x =
0. 5. 10.
Limites
-->x = linspace(0,10,6)
x =
0. 2. 4. 6. 8. 10.
Figura 222: Usando a funo linspace para construir vetores com valores regularmente espaados
Para se obter matrizes onde todos os elementos tm o valor 0 ou o valor 1, podem ser
utilizadas as funes zeros e ones, como mostrado na Figura 223.
-->x = zeros(2,3)
x =
0. 0. 0.
0. 0. 0.
-->y = ones(2,3)
y =
1. 1. 1.
1. 1. 1.
Figura 223: Matrizes com todos os elementos iguais a 0 ou iguais a 1
Outra matriz que se pode obter a matriz identidade, atravs da funo eye, como vemos na
Figura 224.
-->I = eye(4,4)
I =
1. 0. 0. 0.
0. 1. 0. 0.
0. 0. 1. 0.
0. 0. 0. 1.
Figura 224: Obtendo uma matriz identidade com a funo eye
Matrizes com elementos randmicos so muito teis para programas que fazem simulaes de
eventos aleatrios, como a chegada de um carro em uma fila. A funo rand gera matrizes
onde cada elemento um nmero entre 0 e 1, sorteado a cada chamada da funo. A Figura
225 mostra dois exemplos de uso desta funo.
Gera nmeros
aleatrios entre Novos nmeros
0e1 a cada
chamada
-->m = rand(2,3)
m =
0.2113249 0.0002211 0.6653811
0.7560439 0.3303271 0.6283918
-->n = rand(2,3)
n =
0.8497452 0.8782165 0.5608486
0.6857310 0.0683740 0.6623569
Figura 225: Matrizes randmicas
Algumas vezes conveniente gerar matrizes aleatrias com valores inteiros entre, digamos, 0
e 100. Isto se faz com um comando como m = int(rand(2,3)*100), muito til para
quem, como o autor destas linhas, necessita com freqncia de exemplos de matrizes com
valores inteiros. A funo int retorna a parte inteira de seu argumento.
-->x = [1 2; 3 4];
-->y = [10 20; 30 40];
-->z = [x y]
z =
1. 2. 10. 20.
3. 4. 30. 40.
-->z = [x ; y]
z =
1. 2.
3. 4.
10. 20.
30. 40.
Figura 226: Construindo matrizes por justaposio de matrizes j existentes
-->x = 0:0.8:%pi
x =
-->y = sin(x)
y =
A Figura 227 mostra outra forma de se construir uma matriz a partir de uma matriz j
existente, atravs da aplicao de uma funo elementar do Scilab a uma matriz. A matriz
produzida tem as mesmas dimenses da matriz passada como argumento, e cada elemento
resulta da aplicao da funo ao elemento correspondente da matriz original.
-->plot2d(x,y)
15
7,15
14
13
1,12 12
11
10
7 11,7
6
1 2 3 4 5 6 7 8 9 10 11
A Figura 228 mostra um exemplo de grfico obtido com o comando plot2d; outro exemplo
est na Figura 229, que mostra que polgonos arbitrrios podem ser traados com plot2d.
Uma infinidade de parmetros pode ser utilizada no comando plot2d, determinando cores e
espessuras de linhas, tracejados, escalas, etc. Neste curso ns veremos apenas comandos
bsicos; voc pode usar o help do Scilab para saber mais e obter um grfico com um
acabamento melhor.
-->plot2d(x,y)
4,7
3,4
2,3
5,1
Figura 229: Outro exemplo de grfico obtido com plot2d
Para se obter um grfico da funo seno, podemos fazer como mostrado na Figura 230.
Primeiramente gerado o vetor x de abscissas depois, o vetor y obtido pela aplicao da
funo sin ao vetor x, e o comando plot2d(x,y) gera o grfico.
-->x = 0:0.8:3*%pi;
-->y = sin(x);
-->plot2d(x,y)
1.0
0.8
0.6
0.4
0.2
O espaamento 0.0
grande! -0.4
-0.6
-0.8
-1.0
0 1 2 3 4 5 6 7 8 9
A curva obtida no merece bem este nome: est toda quebrada, com cotovelos visveis. o
nmero de pontos utilizado para as abscissas foi pequeno para a nossa acuidade visual. Um
resultado melhor (e que mostra que a gerao de um vetor pela funo linspace mais
confortvel nessas ocasies) est mostrado na Figura 231.
-->x = linspace(0,3*%pi,101)
-->y = sin(x);
-->plot2d(x,y
32
A funo plot2d pode ser usada para traar vrias curvas em um nico grfico. O comando
plot2d(x,M) , onde x um vetor coluna, e M uma matriz com o mesmo nmero de linhas
de x faz um grfico de x versus cada coluna de M.
-->x = linspace(0, 3*%pi, 101)';
-->plot2d(x,[sin(x) sin(2*x) sin(3*x)])
1.0
0.8
0.6
x um vetor
0.4
coluna (e
sin(x),
0.2
0.0
-0.2
sin(2*x) e
-0.4
sin(3*x)
-0.6 tambm so)
-0.8
-1.0
0 1 2 3 4 5 6 7 8 9 10
A Figura 232 mostra um grfico obtido dessa forma. Repare que o vetor x um vetor coluna, e
que, como na Figura 226, a matriz cujas colunas so mostradas no grfico construda por
justaposio dos vetores coluna sin(x) , sin(2*x) e sin(3*x).
possvel ler um arquivo e transformar cada uma de suas linhas em um elemento de um vetor
coluna de strings. Para isso deve ser usado o comando mgetl(da), onde da um descritor
de arquivo j aberto.
fpath = uigetfile()
da = mopen(fpath,'r')
linhas = mgetl(da);
mclose(da);
Figura 234: Leitura de um arquivo como um vetor coluna de strings usando o comando mgetl
A Figura 234 mostra um uso tpico do comando mgetl, precedido pela localizao e da
abertura do arquivo, e seguido pelo fechamento do arquivo.
-->linhas
linhas =
!E agora, Jos? !
!A festa acabou, !
!a luz apagou, !
!o povo sumiu, !
!a noite esfriou, !
!e agora, Jos? !
!e agora, voc? !
!voc que sem nome, !
!que zomba dos outros, !
!voc que faz versos, !
!que ama, protesta? !
!e agora, Jos? !
Figura 235: Arquivo fonte visto com o Bloco de Notas e vetor de strings obtido com o comando mgetl
Na Figura 235 ns vemos o efeito desses comandos quando o arquivo escolhido para leitura
o mostrado na parte esquerda da figura, com o famoso poema do Drummond.
a = [1 2 3; 4 5 6; 7 8 9];
arq = uigetfile();
Cabecalho = [" Meus Dados "; "Col1 Col2 Col3"]
fprintfMat(arq,a,"%5.2f",Cabecalho);
Figura 236: Gravao de uma matriz em um arquivo com fprintfMat
arquivo = uigetfile();
m = fscanfMat(arquivo)
Figura 238: Leitura de uma matriz com o comand fscanfMat
Vamos agora ver um exemplo de aplicao de matrizes e arquivos. A Figura 239 mostra o
arquivo TempoBHZ.txt exibido com o Bloco de Notas. Cada linha do arquivo contm o nmero
de um ms, a temperatura mdia mxima do ms, a temperatura mnima mdia, a mxima
record, a mnima record, e a precipitao do ms em milmetros de chuva.
arqClima = uigetfile();
ClimaBH = fscanfMat(arqClima);
MaxMed = ClimaBH(:,2); // MaxMed = 2a coluna
MinMed = ClimaBH(:,3); // MinMed = 3a coluna
MaxRec = ClimaBH(:,4); // MaxRec = 4a coluna
MinRec = ClimaBH(:,5); // MinRec = 5a coluna
Precip = ClimaBH(:,6); // Precip = 6a coluna
plot2d([1:12],[MaxMed MinMed MaxRec MinRec],...
leg="MaxMed@MinMed@MaxRec@MinRec")
xtitle("Temperaturas Mensais em BH","Ms","Graus C");
Figura 240: O programa ClimaBHZ.sce
A Figura 240 mostra o programa ClimaBHZ.sce que atende a essa especificao. Como voc
pode ver, o programa bastante simples, com a descoberta e leitura do arquivo, seguida das
extraes das colunas, e seguida da gerao do grfico. to simples que aproveitamos para
introduzir duas novas tcnicas que podem melhorar a apresentao de um grfico:
o parmetro extra de plot2d, leg="MaxMed@MinMed@MaxRec@MinRec", que
gera legendas para cada curva em no grfico, e
o comando xtitle, que determina ttulos para o grfico e para cada um dos eixos.
Temperaturas Mensais em BH
40
35
30
25
Graus C
20
15
10
0
0 2 4 6 8 10 12
MaxMed MinRec
Ms
MinMed
MaxRec
Figura 241: Grfico gerado pelo programa da Figura 240
Na Figura 241 voc pode ver o efeito destas tcnicas sobre o grfico.
Uma expresso relacional envolvendo matrizes pode ser empregada em um comando if, mas
isso deve ser feito com muito cuidado, pois a clusula then s ser executada se todos os
elementos da matriz booleana resultante forem iguais a %t. A Figura 243 mostra um exemplo,
onde somente o segundo if tem a sua clusula then executada, pois a matriz resultante da
comparao a > 0 tem todos os elementos iguais a %t.
-->a = [3 9; 12 1]
-->x = 0; y = 0;
-->if a > 5 then; x = 10000; end;
-->if a > 0 then; y = 10000; end;
-->[x y]
ans =
0. 10000.
Figura 243: Exemplos de emprego de expresses relacionais matriciais em comandos if
Se A for uma matriz e MB uma matriz booleana com as mesmas dimenses de A, A(MB)
designa aqueles elementos de A com correspondentes em MB iguais a %t. Isso nos permite
selecionar elementos de uma forma elegante, como mostra a Figura 244
-->a = [3 9; 12 1];
-->a(a>5) = -1
a =
3. - 1.
- 1. 1.
Figura 244: Exemplo de seleo de elementos de uma matriz por uma matriz booleana
3.3 Funes
Funes so uma ferramenta de modularizao da mais alta importncia para a programao
em Scilab. Elas permitem o reaproveitamento de cdigo, a diviso de tarefas em projetos
maiores de programao, e tornam o cdigo mais legvel.
Para ilustrar o uso de funes, vamos desenvolver um programa que l dois inteiros, e , e
que calcula e imprime o nmero de combinaes de tomados a , dado pela frmula
Temos trs fatoriais a calcular, e para isso, vamos procurar reaproveitar o cdigo que
conhecemos para o clculo do fatorial, mostrado na Figura 245.
fat = 1;
for i = 1:n
fat = fat*i;
end
Figura 245: Trecho de cdigo para o clculo do fatorial
A adaptao deste cdigo aos trs fatoriais necessrios para o clculo do nmero de
combinaes nos leva ao programa mostrado na Figura 246, onde cada clculo de fatorial est
destacado, e onde o comando de sada foi omitido.
n=input("n="); k=input("k=");
fat_n = 1; // Clculo do fatorial de n
for i = 2:n
fat_n = fat_n * i;
end
fat_n_k = 1; // Clculo do fatorial de n-k
for i = 2:(n-k)
fat_n_k = fat_n_k * i;
end
fat_k = 1; // Clculo do fatorial de k
for i = 2:k
fat_k = fat_k * i;
end
nComb = fat_n/(fat_n_k * fat_k)
Figura 246: Programa para clculo do nmero de combinaes de n k a k
Voc pode reparar que foram feitas trs adaptaes do cdigo, uma para cada fatorial a ser
calculado. Ns vamos mostrar que com o uso de funes este programa se torna muito mais
claro. Para isso vamos dividir o programa em duas partes: o programa principal e a funo.
n=input("n="); k=input("k=");
nComb = fatorial(n) / (fatorial(n-k) * fatorial(k))
Figura 247: Programa principal para o clculo de combinaes
O programa da Figura 247 faz a mesma coisa, utilizando a funo fatorial cujo cdigo est
na Figura 248.
O programa da Figura 247 contm chamadas da funo fatorial; como usa funes,ele
recebe a designao de programa principal. A execuo de um programa com funes se inicia
pelo programa principal. A execuo de uma chamada transfere o controle para a funo; ao
trmino da execuo da funo, o controle devolvido para o ponto de chamada, em uma
operao que chamamos de retorno da funo.
A cada chamada, um parmetro da funo utilizado, o que permite um reaproveitamento de
cdigo muito mais elegante. A leitura do programa principal tambm muito mais fcil; a
inteno do programador mais clara. Para algum que no tivesse construdo o programa da
Figura 246, a percepo da similaridade entre os trechos de clculo do fatorial pode no ser
bvia, e requer esforo de verificao. Para o prprio programador, as substituies utilizadas
para a construo do programa da Figura 246 so uma fonte de enganos.
3.3.1 Sintaxe
Uma funo pode ter mais de um parmetro formal de sada; a Figura 251 mostra um exemplo
de definio e de chamada de uma funo com dois parmetros formais de sada.
Uma funo cria um espao novo para variveis, que podem ter nomes iguais aos de variveis
j definidas no programa principal. Variveis definidas por uma funo so chamadas variveis
locais. Na funo da Figura 248 a varivel i uma varivel local; o programador desta funo
no precisa se preocupar com qualquer outra varivel de mesmo nome definida no programa
principal. Essa delimitao de escopo de variveis uma propriedade essencial para permitir o
desenvolvimento de funes por programadores independentes; se no existisse, todos os
programadores participantes de um projeto de maior vulto teriam que se preocupar com a
escolha de nomes de variveis no utilizados por seus colegas.
A Figura 252 mostra o arquivo com a funo da Figura 251 aberto no Scipad, onde voc pode
reparar que o arquivo e a funo tm o mesmo nome, sendo que o arquivo tem a extenso
.sci.
A mera existncia de um arquivo com uma funo no basta para que o Scilab saiba de sua
existncia. necessrio incorporar a funo ao Scilab, o que pode ser feito com o comando
exec(<nome do arquivo com a funo>)
que deve ser colocado no programa principal. Um exemplo de uso do comando exec est
mostrado na Figura 253.
exec("fatorial.sci")
n=input("n="); k=input("k=");
nComb = fatorial(n) / (fatorial(n-k) * fatorial(k))
Figura 253: Programa principal para o clculo de combinaes com o comando exec
Ateno: o arquivo com a funo deve estar no mesmo diretrio em que se encontra o
programa principal, e este deve ser o diretrio corrente do Scilab (veja a Seo 3.1).
Parmetros de entrada e de sada de uma funo podem ser qualquer coisa: nmeros, strings,
booleanos, arrays de qualquer tipo, e at mesmo outra funo! A Figura 254 mostra um
exemplo de uma funo que recebe uma funo f como parmetro e que faz o seu grfico
para um vetor x.
function PlotaPontos(f,x)
y = f(x);
plot2d(x,y,style=-1);
endfunction
Figura 254: Uma funo que faz o grfico de outra funo recebida como parmetro
O clculo de combinaes uma operao que pode ser aproveitada em outras ocasies.
Como vimos, o cdigo de uma funo mais facilmente reaproveitado do que o cdigo de um
programa. Uma boa idia ento transformar o programa da Figura 253 em uma funo, o
que resulta no cdigo mostrado na Figura 255.
Um programa principal equivalente ao da Figura 247 est mostrado na Figura 256. Voc deve
reparar no encadeamento de chamadas: o programa principal chama a funo
Combinacoes, que por sua vez chama por trs vezes a funo fatorial.
exec("Combinacoes.sci")
exec("fatorial.sci")
n=input("n="); k=input("k=");
printf("nComb(%d,%d) = %d",n,k,Combinacoes(n,k))
Figura 256: Um programa principal que usa a funo Combinacoes
Programa
Principal
Funo
nComb
Funo
Fatorial
function s = Soma(A)
// Calcula a soma dos elementos do vetor A
endfunction
Figura 258: Cabealho da funo Soma
Salve este arquivo no seu diretrio de trabalho com o nome Soma.sci. Com isto j
escrevemos o cabealho da funo, ou seja:
demos um nome significativo funo,
determinamos e demos nomes para seus parmetros formais de entrada e de sada.
Como vimos, parmetros formais so utilizados no cdigo da funo; parmetros reais so os
parmetros utilizados no momento da chamada da funo. Tanto para entender melhor a
relao entre parmetros formais e reais como para testar a nossa funo, vamos construir um
programa que ir utilizar a funo Soma, gerando e calculando a soma dos elementos de
vetores aleatrios. Para isto, no Scipad use o menu File/New, digite um programa como o da ,
Figura 259, e salve-o com o nome TestaSoma.sce.
Figura 260: Tela do Scipad dividida em duas janelas pelo menu Windows/Split(side by side)
Como faremos para calcular a soma de todos os elementos do vetor A? Vamos avanar aos
poucos. Suponhamos que uma varivel s contenha o valor dos primeiros k elementos de A,
ou seja, suponhamos que de alguma forma ns conseguimos colocar em s o valor de A(1)
+ A(2) + ... + A(k). No difcil ver que, se fizermos s = s + A(k+1), s
passar a conter o valor dos primeiros k+1 elementos de A. Se depois disso fizermos s = s
+ A(k+2), s passar a conter o valor dos primeiros k+2 elementos de A. Se repetirmos
este passo at atingir o ltimo elemento de A, teremos em s a soma de todos os elementos
de A, como desejvamos. A Figura 261 ilustra um passo deste algoritmo.
Sabemos portanto como avanar no clculo da soma, mas como comear? No caso, simples.
Quando k=0, a parte do vetor com os k primeiros elementos vazia, e portanto, sabemos que
s = 0 para k = 0.
Para k = 0,
s =0
1 2 3 4 5 6 7 8 9 10
44 13 44 46 29 30 34 34 42 13
Para k = 3, Para k = 4,
s = 101 s = 101 + 46 = 147
Figura 261: Um passo do algoritmo de soma
Falta ainda saber como terminar, dado que, a cada chamada, a funo poder receber
argumentos reais de tamanhos diferentes. O problema que, ao programar a funo, no se
sabe qual o tamanho do parmetro formal A. Para isto a funo length de grande valia.
Se M uma matriz, length(M) retorna o produto do nmero de linhas pelo nmero de
colunas de M. Se M um vetor, ou bem o nmero de linhas ou bem o nmero de colunas de M
igual a 1, e portanto, length(M) nos fornece o nmero de elementos de M.
Com isto chegamos verso final da funo Soma, mostrada na Figura 262.
function s = Soma(A);
// Calcula a soma dos elementos do vetor A
s = 0;
for k = 1:length(A)
s = s + A(k);
end
endfunction
Figura 262: Verso final da funo Soma
sa = Soma(a);
!--error 4
undefined variable : Soma
at line 3 of exec file called by :
dores\Scilab\TestaSoma.sce');disp('exec done')
Figura 263: Erro ao tentar executar o programa TestaSoma
b = int(10*rand(1,6))
sb = Soma(b);
printf("\n Soma = %g\n", sb);
c = int(10*rand(1,9))
sc = Soma(c);
printf("\n Soma = %g\n",sc);
Figura 264: O programa TestaSoma.sce, agora com exec
-->exec('C:\Documents and
Settings\usuario\Desktop\Scilab\TestaSoma.sce');disp('exec
done');
a =
3. 3. 2. 5.
Soma = 13
b =
4. 3. 5. 5. 4. 2.
Soma = 23
c =
6. 4. 9. 0. 4. 2. 4. 2. 1.
Soma = 32
exec done
Figura 265: Uma possvel sada do programa TestaSoma.sce
function m = Minimo(A)
// Encontra o menor valor presente no vetor A
endfunction
Figura 266: Cabealho da funo Minimo
Muito bem, temos o cabealho da funo Minimo, temos um programa testador, e agora
vamos desenvolver a funo propriamente dita. Vamos procurar seguir um raciocnio similar
ao utilizado para o clculo da soma dos elementos de um vetor. Suponhamos que uma varivel
m contenha em um dado momento o menor valor entre os primeiros k elementos do vetor.
Para avanar simples:
comparamos o valor de m com o valor de A(k+1) ;
se m for menor ou igual a A(k+1) , seu valor j tambm o menor entre os
primeiros k+1 elementos do vetor (podem haver empates, mas isto no um
problema) e pode permanecer inalterado;
se m for maior que A(k+1) , devemos fazer m = A(k+1) para que seu valor passe
a ser o menor entre os primeiros k+1 elementos do vetor.
Figura 267: Dois passos do algoritmo que encontra o menor valor presente em um vetor
A Figura 267 ilustra dois passos deste algoritmo. No difcil acreditar que ns encontraremos
o menor valor presente no vetor aplicando repetidamente os passos acima at encontrarmos
o limite superior do vetor.
Precisamos entretanto de um ponto de partida para o algoritmo. Isto pode ser facilmente
obtido, pois claro que, para k == 1 , A(1) o menor elemento entre os k (=1) primeiros
elementos de A, no ? Podemos agora chegar verso final da funo Minimo, mostrada na
Figura 268.
function m = Minimo(A)
// Encontra o menor valor presente no vetor A
m = A(1);
for k = 2:length(A)
if m > A(k)
m = A(k);
end
end
endfunction
Figura 268: A funo Mnimo
Execute agora o programa TestaMinimo.sce; voc dever obter uma sada parecida com a
Figura 269.
a =
5. 4. 2. 8.
Mnimo = 2
b =
1. 2. 8. 8. 5. 9.
Mnimo = 1
c =
6. 9. 0. 7. 4. 6. 8. 0. 8.
Mnimo = 0
exec done
Figura 269: Sada do programa TestaMinimo.sce
3.3.4 Recursividade
Ns vimos que uma funo pode chamar outra funo, que pode chamar outra funo, que
pode chamar outra funo, em um encadeamento de chamadas de profundidade arbitrria.
Uma funo pode tambm chamar a si prpria, o que a torna uma funo recursiva. Ns
veremos ao longo desse curso que uma formulao recursiva muitas vezes a forma mais
natural para a descrio de um algoritmo.
Como um primeiro exemplo, vamos mostrar uma funo recursiva para o clculo do fatorial de
um nmero. Ns sabemos que
e que, para ,
A funo fatorialR na Figura 270 calcula o fatorial de um nmero usando de forma muito
natural essas equaes.
// Teste de FatorialR
exec("FatorialR.sci");
n = input("n = ");
while n > 0 do
printf("\n%d! = %d",n,FatorialR(n));
n = input("n = ");
end
Figura 271: Programa TestaFatorialR.sce
A execuo deste programa pode gerar a sada mostrada na Figura 273, onde acrescentamos
chaves para indicar a correspondncia entre chamadas e retornos da funo.
n = 5
Iniciando FatorialR(5)
Iniciando FatorialR(4)
Iniciando FatorialR(3)
Iniciando FatorialR(2)
Iniciando FatorialR(1)
Retornando Fatorial(1) = 1
Retornando Fatorial(2) = 2
Retornando Fatorial(3) = 6
Retornando Fatorial(4) = 24
Retornando Fatorial(5) = 120
5! = 120
Figura 273: Sada do programa TestaFatorialR.sce
Fat(1)
Fat(2) Fat(2) Fat(2)
Fat(3) Fat(3) Fat(3) Fat(3) Fat(3)
Fat(4) Fat(4) Fat(4) Fat(4) Fat(4) Fat(4) Fat(4)
Fat(5) Fat(5) Fat(5) Fat(5) Fat(5) Fat(5) Fat(5) Fat(5) Fat(5)
Prog Prog Prog Prog Prog Prog Prog Prog Prog Prog Prog
Figura 274: Pilha de execuo de FatorialR
function m = MinimoR(x)
if length(x) == 1 then
m = x(1)
else
half = int(length(x)/2);
minLeft = MinimoR(x(1:half));
minRight = MinimoR(x(half+1:length(x)));
if minLeft <= minRight then
m = minLeft
else
m = minRight
end
end
endfunction
Figura 275: Funo MinimoR, recursiva
Construir um programa que, seguindo a estrutura mostrada na Figura 186, leia uma srie de
dados, faa alguma coisa com eles, e termine conforme o desejo do usurio, uma idia que j
foi explorada por diversas vezes neste curso. Encontrar o menor primo maior ou igual a um
nmero lido nos parece complicado, mas vamos dar incio ao desenvolvimento do programa
deixando isso para depois. Veja uma proposta na Figura 276.
Podemos ver que o programa principal cuida da interao com o usurio, empurrando o
problema de se encontrar o menor primo para uma funo MenorPrimoMaiorOuIgualA,
que ainda no existe. No existe, mas j demos a ela um nome significativo, e especificamos
que:
A funo tem um nico parmetro de entrada, que o nmero digitado pelo usurio
A funo deve retornar o nmero primo que desejamos.
Ou seja, j definimos o cabealho da funo MenorPrimoMaiorOuIgualA. Muito bem,
vamos agora encarar o seu desenvolvimento. O algoritmo simples: vamos testar
sequencialmente os inteiros a partir do nmero lido, parando ao encontrar um nmero primo.
Sim, mas como vamos saber se um inteiro primo? No vamos nos preocupar com isso agora.
Outra vez, vamos especificar uma funo e adiar o problema. Veja a Figura 277.
function p = MenorPrimoMaiorOuIgualA(n)
p = n;
while ~Primo(p)
p = p+1
end
endfunction
Figura 277: A funo MenorPrimoMaiorOuIgualA
function p = MenorFator(n)
p = 2;
while modulo(n,p) <> 0
p = p + 1;
end
endfunction
Figura 279: A funo MenorFator
0
0 1 2 3 4 5 6
0
0 1 2 3 4 5 6
Repare que foram utilizados dois pares de vetores, um para cada polgono desenhado. Quando
temos muitos polgonos a desenhar, como o caso do mapa que faremos em seguida, torna-se
interessante representar todos os polgonos em um nico par de vetores com as coordenadas
de todos os vrtices. preciso entretanto encontrar um meio de informar ao Scilab quais so
os pontos que separam dois polgonos. Isto porque se fizermos
--> X = [x w];
--> Y = [y z];
--> plot2d(X,Y,rect=[0 0 6 6]);
vamos obter o desenho da Figura 282, onde o ponto final do primeiro polgono e o ponto
inicial do segundo polgono foram (naturalmente) emendados pelo Scilab.
0
0 1 2 3 4 5 6
Este problema resolvido inserindo-se pares de pontos com coordenadas iguais a %inf
(representao de infinito em ponto flutuante; veja a Seo 2.1) para indicar ao Scilab os
pontos de separao entre dois polgonos. Experimente agora fazer, na console do Scilab,
--> X = [x %inf w];
--> Y = [y %inf z];
--> clf
--> plot2d(X,Y,rect=[0 0 6 6]);
e voc obter a figura desejada, com polgonos separados. O comando clf limpa a janela
grfica do Scilab.
Um mapa simples pode ser representado por uma tabela de pares latitude-longitude. Em
princpio estas tabelas podem ser utilizadas diretamente para o desenho dos mapas utilizando
a funo plot2d mas, como j vimos, necessrio algum mecanismo para separar os
polgonos isolados representando cada ilha, lago ou continente.
No nosso site, faa o download do arquivo world.txt (que obtivemos na referncia
(Wolffdata), e de onde retiramos grande parte desta seo), e abra-o utilizando o Bloco de
Notas (Notepad). Um pequeno exame desse arquivo basta para verificar que a separao entre
os polgonos est ali representada pelas coordenadas com valores 9999.
Faa agora um programa que
1) Leia este arquivo em uma matriz Mapas. Use para isto as funes uigetfile e
fscanfMat.
2) Extraia desta matriz dois vetores, Lat e Long, correspondendo s duas colunas da
matriz lida.
3) Utilize uma funo colocaInfinito para substituir nos vetores Lat e Long os
valores 9999 por %inf. Para isto construa na sua funo um loop que faa uma
varredura completa do vetor que receber como parmetro de entrada, e fazendo a
substituio quando for o caso. Use a funo length(x) (que devolve o nmero de
elementos em um vetor linha ou coluna) para determinar o limite superior de seu
loop.
4) Use plot2d para obter o desenho do mapa representado no arquivo.
5) Utilize uma funo suaviza para construir os vetores LatS e LongS a partir dos
vetores Lat e Long, utilizando a regra
LatS(i) = (Lat(i-1)+Lat(i)+Lat(i+1))/3
se Lat(i-1), Lat(i) e Lat(i+1) forem diferentes de infinito, e LatS(i) =
Lat(i) no caso contrrio. Esta regra deve ser usada para os valores de i entre 2 e
length(Lat)-1; para os extremos do vetor, temos LatS(1) = Lat(1), e
LatS(length(Lat)) = Lat(length(Lat)). A construo de LongS
similar.
6) Utilize a funo scf(3) para abrir outra janela grfica, e faa
plot2d(LatS,LongS) para descobrir o efeito da suavizao.
4 Algoritmos
4.1 Definio e Caractersticas
Um problema de transformao de informao descreve uma entrada de informao e
propriedades requeridas de uma informao de sada. Um algoritmo resolve um problema de
transformao, sendo constitudo por uma prescrio de passos que transformam uma
informao de entrada em outra informao de sada. Cada passo prescrito deve ser uma
operao garantidamente realizvel, seja por operaes elementares, seja por outro
algoritmo. Um programa a concretizao de um algoritmo em uma linguagem executvel.
Trs questes so bsicas para a caracterizao de problemas e algoritmos:
Especificao: qual exatamente o problema de transformao de informao que
queremos resolver?
Correo: um dado algoritmo resolve mesmo o problema proposto em sua
especificao?
Eficincia: com qual consumo de recursos computacionais (essencialmente, tempo e
memria) o algoritmo executa a sua funo?
Ns iremos a seguir detalhar um pouco mais cada uma dessas questes.
4.1.1 Especificao
Especificaes surgem de um processo de anlise de uma necessidade de transformao de
informao. Uma especificao no esttica; muitas vezes uma especificao modificada
durante e mesmo aps o processo de desenvolvimento de um programa. Uma condio no
prevista muitas vezes a causa de uma alterao em uma especificao. Como um exemplo,
no programa que vimos para a soluo de muitas equaes de 2 grau com coeficientes em
um arquivo (Figura 200), ns no demos um tratamento especial para o caso de termos o
primeiro coeficiente nulo, o que provoca uma diviso por zero no clculo das raizes. Se em
uma linha do arquivo de coeficientes tivermos , a diviso por zero provocar uma
interrupo da execuo do programa, sem o processamento das equaes restantes. Se isso
no for um comportamento aceitvel, necessrio modificar a especificao para dar um
tratamento adequado a esta situao, que poderia ser, por exemplo, ignorar a linha com
, ou seno resolver a equao de primeiro grau resultante.
Em problemas reais comum que a fase de especificao seja a etapa mais demorada e a mais
cara de um projeto de desenvolvimento de um programa. No existe situao pior para uma
equipe de desenvolvimento do que, ao dar por terminado um sistema, constatar que ele no
atende s necessidades do cliente, necessidades que, por deficincias no processo de anlise,
no foram explicitadas na especificao.
Apesar dessa importncia, neste curso ns procuraremos lidar com problemas cuja
especificao bem simples, pois nosso objetivo aqui a criao de uma cultura algortimica
para o aluno. Tcnicas de anlise e de especificao de sistemas so matrias que voc poder
depois estudar em cursos de engenharia de software.
4.1.2 Correo
possvel verificar se um algoritmo atende a uma especificao por um exame de sua
estrutura, com a construo de uma prova formal de sua correo. Na prtica somente
algoritmos muito pequenos tm uma prova formal de correo vivel. O que se faz produzir
uma argumentao informal da correo de um algoritmo; alm desta argumentao, testes
SC SC SC SC
Usando um exemplo retirado de (Dijkstra, 1972) vamos considerar uma transformao bsica
de informao, feita por um somador em cascata similar ao mostrado na Figura 283, mas com
largura de 32 bits. Se algum quiser considerar o somador como uma caixa preta a ser testada,
teramos (considerando as duas entradas de 32 bits cada) valores para as entradas a serem
testadas, o que claramente inexeqvel. Uma argumentao baseada na estrutura do
somador o que nos propicia a convico de sua correo. Se estamos convencidos da
correo de um circuito de soma completa, como o mostrado na Figura 71 (e estamos, pela
forma de desenvolvimento a partir da tabela da verdade), e se compreendemos a lgica do
arranjo em cascata, no temos dificuldades para acreditar no bom funcionamento do somador
de 32 bits.
A compreenso completa da estrutura de um programa grande estamos falando de milhares
ou mesmo milhes de linhas de cdigo, produzidas por vrios desenvolvedores por sua vez
dificilmente atingvel. No possvel testar completamente um programa, e nem possvel
compreender completamente sua estrutura. E agora, Jos? Bom, isso mesmo. No existe
uma boa sada. A indstria de software investe em qualidade de desenvolvimento, em testes,
mas quase sempre vende programas sem garantia.
Neste curso ns iremos trabalhar com programas pequenos, todos com menos de 50 linhas. A
convico de correo ser tratada tanto com argumentos estruturais como por testes.
Para ganharmos algum sentimento de como algoritmos que satisfazem uma mesma
especificao podem diferir em eficincia, ns vamos fazer alguns experimentos de medidas
de tempo gasto com a fatorao de nmeros inteiros, um problema de importncia
fundamental para a rea de segurana da informao. A segurana da criptografia da maior
parte dos sistemas atuais depende da dificuldade da fatorao de nmeros semi-primos, isto
, nmeros que so formados pelo produto de dois primos. Estamos aqui falando de nmeros
grandes: chaves criptogrficas atuais tm costumeiramente 1024 ou 2048 bits, que
correspondem a nmeros com 308 ou 616 algarismos decimais.
O Scilab oferece a funo timer() que permite medir o tempo gasto na execuo de trechos
de um programa. A primeira execuo da funo timer() zera e dispara um cronmetro;
cada chamada subseqente da funo timer() retorna o valor em segundos do tempo
decorrido desde a chamada anterior da funo.
n = 131101
Tempo = 3.062500s, 131101 divisvel por 131101 **PRIMO**
n = 131103
Tempo = 0.000000s, 131103 divisvel por 3
Figura 285: Tempos para fatorar nmeros primos e no primos
observao: algoritmos podem ter seu tempo de execuo dependente da instncia especfica
do problema que resolve.
Muitas vezes ns estamos interessados na anlise do pior caso de um algoritmo. Ns iremos
em seguida relatar outros experimentos feitos com o programa Fatora.sce. Nestes
experimentos ns vamos precisar de nmeros primos, e para isso o arquivo 200000primos.txt,
que contm os 200.000 primeiros nmeros primos, de grande utilidade. Diversos sites na
Internet, como (Andrews), contm arquivos com nmeros primos ou programas que geram
nmeros primos. A Figura 286 mostra as primeiras e ltimas linhas deste arquivo.
n = 131101
Tempo = 2.984375s, 131101 divisvel por 131101 **PRIMO**
n = 131101
Tempo = 3.078125s, 131101 divisvel por 131101 **PRIMO**
n = 131101
Tempo = 3.015625s, 131101 divisvel por 131101 **PRIMO**
Figura 287: Variaes no tempo de execuo de um programa com os mesmos dados de entrada
Voc pode ver que um mesmo programa apresenta variaes no tempo gasto para a fatorao
do mesmo nmero primo. Isso se deve a uma srie de fatores, o principal deles sendo o fato
de que, em um sistema operacional como o Windows ou o Linux, um programa no executa
sozinho, mas compartilha o processador e outros recursos do computador com outros
programas e com o prprio sistema operacional. Esse compartilhamento coordenado pelo
sistema operacional, e o programador Scilab no tem qualquer controle sobre a forma como
se d este compartilhamento. por isso que uma mesma funo, chamada com os mesmos
parmetros, pode apresentar diferenas de desempenho a cada execuo.
Tabela 16: Tempos (segundos) gastos com a funo MenorFator em um notebook e em um desktop
Figura 288: Tempo para fatorao em funo do valor de nmeros primos em dois computadores
Figura 289: Tempos para fatorao em funo do nmero de bits de um nmero primo em dois computadores
function p = MenorFator2(n)
limite = int(sqrt(n));
p = 2;
while modulo(n,p) <> 0 & p <= limite
p = p + 1;
end
if modulo(n,p) <> 0 then
p = n;
end
endfunction
Figura 290: A funo MenorFator2
Uma anlise direta da funo MenorFator2 mostra que so realizadas chamadas da funo
mdulo em nmero igual raiz quadrada do valor do nmero primo sendo fatorado. Portanto,
sua complexidade . Experimentamos a funo MenorFator2
para verificar fatorar 2750159, o maior primo presente no arquivo 2000000primos.txt, e o
tempo gasto no desktop foi de 0,047 segundos, enquanto que a funo MenorFator gastou
88,360 segundos, uma diferena enorme de desempenho. Quando , a funo modulo
chamada aproximadamente 1024 vezes pela MenorFator, e somente 32 vezes pela
MenorFator2. Quando , a funo modulo chamada aproximadamente
vezes pela MenorFator, e 1024 vezes pela MenorFator2. Ao passar o nmero
de bits da entrada de 10 para 20, a MenorFator demora 1024 vezes mais, enquanto a
MenorFator2 demora 32 vezes mais.
A Figura 291, extrada do livro (Garey & Johnson, 1979), nos ajuda a formar uma idia do que
esperar do desempenho de algoritmos com funes de complexidade exponencial quando
aplicados a problemas grandes.
n2 M 10 M 31,6 M
n3 Z 4,64 Z 10 Z
n5 W 2,5 W 3,98 W
2n X X + 6,64 X + 9,97
3n Y Y + 4,19 Y + 6,29
Figura 292: Efeito do aumento da velocidade de computadores sobre o tamanho dos problemas resolvveis
4.2 Pesquisa
Vamos agora estudar um problema clssico da Cincia da Computao, que a pesquisa para
verificar se um elemento procurado existe em uma tabela. Extenses deste problema fazem
parte do nosso dia a dia, em mquinas de busca como Google e Yahoo, ou na localizao de
uma palavra em um arquivo. Vamos examinar aqui dois algoritmos: a pesquisa seqencial e a
pesquisa binria. Como um exemplo ns vamos utilizar algoritmos de pesquisa para testar a
primalidade de um nmero, a tabela sendo composta pelos nmeros primos presentes no
arquivo 200000primos.txt. Obviamente isto s funciona para nmeros menores ou iguais ao
maior nmero presente no arquivo, 2750159.
A especificao do problema que iremos resolver de duas maneiras distintas :
Faa um programa que:
Leia o arquivo 200000primos.txt, que contm os primeiros 200000 nmeros primos;
Leia repetidamente nmeros inteiros e, para cada nmero lido, verifique se o nmero
primo pesquisando por ele na tabela;
O programa deve parar quando o nmero lido for 0 (zero).
n = input("n = ");
while n >= 2
timer(); eh_Primo = Primo3(n,tabPrimos); tempoGasto = timer();
// Imprime o resultado
printf("\nTempo gasto = %g segundos", tempoGasto);
if eh_Primo then
printf("\nO nmero %d primo!\n\n",n);
else
printf("\nO nmero %d no primo!\n\n", n)
end
n = input("n = ");
end
Figura 293:O programa VerificaPrimos3.sci, que utiliza pesquisa seqencial
A funo Primo3 apenas um envelope sobre uma funo de pesquisa seqencial, como
mostra a Figura 294.
A funo seqSearch mostrada na Figura 295 implanta uma pesquisa seqencial. Ali
podemos observar que:
function p = seqSearch(key,table)
i = 1;
while i <= length(table) & table(i) ~= key
i = i+1;
end
if i <= length(table) then
p = i;
else
p = -1;
end
endfunction
Figura 295: A funo seqSearch para pesquisa seqencial
function p = BinarySearch(key,table,low,high)
if high < low then
p = -1;
else
m = int((low+high)/2);
if key == table(m) then
p = m;
else
if key < table(m) then
p = BinarySearch(key,table,low,m-1);
else
p = BinarySearch(key,table,m+1,high);
end
end
end
endfunction
Figura 296: A funo recursiva BinarySearch
A Figura 296 mostra uma implementao direta da pesquisa binria como uma funo
recursiva.
o ponteiro high cumpre papel similar, mantendo sempre vlida a afirmativa se key
> table(high), ento key no consta da tabela ;
quando o loop termina, a parte da tabela que pode conter um elemento igual chave
est entre low e high e, pela condio de trmino do loop e pela relao entre low
e high,0 <= high low < = 1.
os testes que sucedem ao loop permitem decidir se a tabela contm ou no um
elemento igual chave procurada.
A anlise da complexidade do pior caso da pesquisa binria simples. A cada passo o tamanho
da parte da tabela que pode conter a chave dividido por 2, e o algoritmo termina quando o
tamanho desta parte igual a 1. Se a tabela tem elementos, teremos no pior caso,
comparaes, onde indica a funo teto, que mapeia um nmero real no menor inteiro
maior ou igual a . No caso da tabela armazenada no arquivo 200000primos.txt, temos no pior
caso comparaes para completar a pesquisa. Compare
isso com o pior caso da pesquisa seqencial, que pode necessitar de 200.000 passos para
terminar. Pior: se a tabela dobrar de tamanho, passando a ter 400.00 elementos, o algoritmo
de pesquisa binria ir passar a necessitar de 19 comparaes, uma a mais, enquanto que o
algoritmo de pesquisa seqencial poderia necessitar de 400.000 passos.
Por estes argumentos algum poderia pensar que, em casos em que temos uma tabela
ordenada, a opo pela pesquisa binria em detrimento da pesquisa seqencial uma escolha
bvia, mas nem sempre este o caso. A pesquisa seqencial mais simples, mais fcil de
programar, e menos propensa a erros de programao. E muitas vezes trabalhamos com
tabelas pequenas, onde a diferena de desempenho entre os dois algoritmos no
importante. Ao programar, nunca se esquea do kiss principle, um acrnimo para uma frase
em ingls que todos os bons programadores dizem a si prprios todos os dias: keep it simple,
stupid. Ou seja, s complique quando inevitvel.
4.3 Ordenao
Outro problema clssico da Cincia da Computao a ordenao, que consiste em, dado um
vetor A, obter outro vetor com os mesmos elementos de A, dispostos em ordem crescente ou
decrescente, como mostra a Figura 298.
1 2 3 4 5 6 7
Vetor no
34 56 27 45 12 44 34 ordenado
1 2 3 4 5 6 7 Vetor
12 27 34 34 44 45 56 ordenado
Figura 298: Ordenao de um vetor
function sA = SelectSort(A)
// Constri o vetor sA com os
// mesmos elementos do vetor A
// dispostos em ordem crescente.
endfunction
Figura 299: Cabealho de uma funo de ordenao
Isso j nos permite desenvolver um programa para testar a funo, mostrado na Figura 300.
exec("SelectSort.sci");
a = int(10*rand(1,4))
aa = SelectSort(a)
b = int(10*rand(1,6))
bb = SelectSort(b)
c = int(10*rand(1,9))
cc = SelectSort(c)
Figura 300: O programa SelectSort_teste.sce
1 2 3 4 5 6 7
34 56 27 45 12 44 34
1 2 3 4 5 6 7
12 56 27 45 34 44 34
1 2 3 4 5 6 7
12 27 56 45 34 44 34
1 2 3 4 5 6 7
12 27 34 45 56 44 34
1 2 3 4 5 6 7
12 27 34 34 56 44 45
1 2 3 4 5 6 7
12 27 34 34 44 56 45
1 2 3 4 5 6 7
12 27 34 34 44 45 56
Figura 301: Ordenao por Seleo e Troca
function sA = SelectSort(A)
for k = 1:length(A)-1
// Seleciona a posio entre A(k) e
// A(length(A)) que contm o menor valor
Como voc pode reparar na Figura 303, as modificaes introduzidas memorizam na varivel
im a posio onde o mnimo corrente foi encontrado (nas situaes em que m atualizada),
restringem o espao da busca apenas aos elementos de A com ndices entre os parmetros de
entrada low e high, e acrescentam um parmetro de sada.
Se a funo Minimo mereceu a construo de um programa para seu teste, uma boa idia
fazer o mesmo para a funo MinimoPos, que um pouco mais complicada. Voc poderia
pensar que, indiretamente, o programa OrdenaPorSelecao_teste j o faria, mas
construir um testador independente tem a vantagem de simplificar o contexto de uso da
funo MinimoPos.
a = int(10*rand(1,10));
PrintMatrix("A",a);
inicio = input("Inicio = ");
fim = input("Fim = ");
while inicio > 0
[m im] = MinimoPos(a,inicio,fim)
inicio = input("Inicio = ");
fim = input("Fim = ");
end
function PrintMatrix(Label, M);
printf("\n%s = [",Label);
for i = 1:length(M)
printf("%3d",M(i));
end
printf("]")
endfunction
Figura 304: O programa MinimoPos_teste e a funo PrintMatrix
A = [ 2 7 0 3 6 6 8 6 8 0]
Inicio = 2
Fim = 5
im =
3.
m =
0.
Inicio = 4
Fim = 6
im =
4.
m =
3.
Figura 305: Uma sada do programa MinimoPos_teste
function sA = SelectSort(A)
for k = 1:length(A)-1
// Seleciona a posio entre A(k) e
// A(length(A)) que contm o menor valor
[Min iMin] = MinimoPos(A,k,length(A));
// Troca os valores de A(k) com o valor
// na posio selecionada.
temp = A(k);
A(k) = A(iMin);
A(iMin) = temp;
end
sA = A;
endfunction
Figura 306: A funo SelectSort
Vamos agora examinar a complexidade deste algoritmo. Para ordenar um vetor de tamanho ,
o primeiro passo do algoritmo de seleo e troca realiza comparaes; o segundo,
; o terceiro, , e assim por diante, at chegar ao ltimo passo, quando feita uma nica
comparao. Podemos concluir que o nmero de comparaes realizado dado por
Figura 307: Tempos medidos para ordenao por seleo e troca de vetores aleatrios em um notebook (*) e em
um desktop (+)
Intercalao de a e b
1 2 3 4 5 6 7 8 9 10
10 15 15 16 19 19 20 22 23 27
Figura 308: Uma operao de intercalao
16 12 72 26 54 98 73 0 59 30 25 62 11 61 67 33 2
8 12 72 26 54 98 73 0 59 30 25 62 11 61 67 33 2
4 12 72 26 54 98 73 0 59 30 25 62 11 61 67 33 2
2 12 72 26 54 98 73 0 59 30 25 62 11 61 67 33 2
1 12 72 26 54 98 73 0 59 30 25 62 11 61 67 33 2
2 12 72 26 54 73 98 0 59 25 30 11 62 61 67 2 33
4 12 26 54 72 0 59 73 98 11 25 30 62 2 33 61 67
8 0 12 26 54 59 72 73 98 2 11 25 30 33 61 62 67
16 0 2 11 12 25 26 30 33 54 59 61 62 67 72 73 98
4
Figura 309: Exemplo de ordenao por intercalao com n = 16 = 2
Os pequenos nmeros no lado esquerdo da figura indicam o tamanho de cada parte. Como 16
uma potncia de dois, a estrutura de divises e intercalaes muito regular. A Figura 310
mostra um exemplo com um vetor de tamanho 10, quando nem sempre as duas partes
resultantes de uma diviso (ou a serem intercaladas) tm o mesmo tamanho.
10 60 85 6 82 92 56 57 81 5 55
5 60 85 6 82 92 56 57 81 5 55
3 60 85 6 56 57 81
2 60 85 82 92 56 57 5 55
1 60 85 6 82 92 56 57 81 5 55
2 60 85 82 92 56 57 5 55
3 6 60 85 56 57 81
5 6 60 82 85 92 5 55 56 57 81
10 5 6 55 56 57 60 81 82 85 92
Figura 310: Exemplo de ordenao por intercalao com n = 10
O cdigo da funo MergeSort est mostrado na Figura 311. Voc deve reparar que o
cdigo transcreve o algoritmo de forma bastante direta, e que pressupe a existncia de uma
funo Merge que realiza as intercalaes.
function sA = MergeSort(A)
if length(A) <= 1 then
sA = A;
else
m = int((1+length(A))/2);
sA = Merge(MergeSort(A(1:m)),...
MergeSort(A(m+1:length(A))));
end
endfunction
Figura 311: A funo MergeSort
A codificao da funo Merge (Figura 312) tambm bastante intuitiva. Voc deve reparar
que:
pA, pB e pM so ponteiros que indicam as posies em foco nos vetores fonte e no
vetor resultado;
O primeiro loop realiza a intercalao propriamente dita, a cada passo colocando em
M(pM) o menor entre A(pA) e B(pB), e avanando adequadamente pA ou pB; este
loop termina quando pA ou pB atinge o limite do seu vetor;
O segundo loop s efetivamente executado quando a sada da fase de intercalao
se deu pelo esgotamento dos elementos de B e consiste em copiar os elementos
restantes de A em M;
Da mesma forma, o terceiro loop s efetivamente executado quando a sada da fase
de intercalao se deu pelo esgotamento dos elementos de A, e consiste em copiar os
elementos restantes de B em M.
function M = Merge(A,B)
pA = 1; pB = 1; pM = 1
while pA <= length(A) & pB <= length(B)
if A(pA) <= B(pB) then
M(pM) = A(pA);
pA = pA+1;
else
M(pM) = B(pB);
pB = pB+1;
end
pM = pM+1;
end
// Esgota A
while pA <= length(A)
M(pM) = A(pA);
pM = pM+1;
pA = pA+1;
end
// Esgota B
while pB <= length(B)
M(pM) = B(pB);
pM = pM+1;
pB = pB+1;
end
endfunction
Figura 312: A funo Merge
1 12 72 26 54 98 73 0 59 30 25 62 11 61 67 33 2
16 passos
4 = log2(16)
2 12 72 26 54 73 98 0 59 25 30 11 62 61 67 2 33
16 passos
4 12 26 54 72 0 59 73 98 11 25 30 62 2 33 61 67
16 passos
8 0 12 26 54 59 72 73 98 2 11 25 30 33 61 62 67
16 passos
16 0 2 11 12 25 26 30 33 54 59 61 62 67 72 73 98
Figura 313: Passos para ordenao por intercalao
Ali vemos o processo ilustrado para um vetor cujo tamanho uma potncia de 2, mas para
outros tamanhos, podemos considerar como limite superior a complexidade exigida para a
menor potncia de 2 que supere o tamanho do vetor. Vamos considerar apenas a fase de
intercalao, ilustrada na parte inferior da figura, uma vez que as divises so feitas com
pouco trabalho computacional. Repare que:
para a ltima intercalao realizada, que gera o vetor ordenado de tamanho a partir
de dois vetores ordenados de tamanho , so feitas no operaes.
para cada intercalao no penltimo nvel, que geram vetores ordenados de tamanho
a partir de vetores de tamanho , so feitas no operaes; como temos
duas intercalaes neste nvel, teremos tambm no mximo comparaes.
o mesmo vale para todos os nveis anteriores; como temos nveis, o nmero
mximo de comparaes realizadas pelo algoritmo de ordenao por intercalao
igual a , e o algoritmo portanto .
Para se ter uma idia da diferena de desempenho entre o algoritmo de seleo e troca e o
algoritmo de intercalao, quando , ,e ; quando ,
,e , e por a vai.
O mtodo que veremos agora para se ordenar um vetor utiliza uma operao de partio do
vetor segundo um piv, que um valor igual a um dos elementos do vetor. A partio,
operao aplicvel somente a vetores com dois ou mais elementos, separa o vetor em trs
partes:
a da esquerda, contendo somente elementos menores ou iguais ao piv,
a do meio, contendo somente elementos iguais ao piv, e
a da direita contendo somente elementos maiores ou iguais ao piv.
possvel que algumas das partes resultantes seja vazia. O mtodo prossegue aplicando-se
recursivamente s parties da esquerda e da direita, at se conseguir parties de tamanho 1
que esto trivialmente ordenadas. Este um dos algoritmos mais famosos da cincia da
computao, tendo recebido o nome de quicksort.
14 0 11 6 5 12 2 12 13 6
2 0 5 6 11 12 14 12 13 6
0 2 5 6 11 12 6 12 13 14
Esquerda
Meio
0 2 5 6 11 12 6 12 13 14
Direita
x Piv
0 2 5 6 6 12 11 12 13 14
0 2 5 6 6 11 12 12 13 14
0 2 5 6 6 11 12 12 13 14
Figura 316: Exemplo de ordenao por partio (quicksort)
function sA = quicksort(A)
if length(A) <= 1 then
sA = A;
else
[l,m,r] = partition(A);
sA = [quicksort(l) m quicksort(r)];
end
endfunction
Figura 317: A funo quicksort, que implementa o algoritmo de ordenao por partio
Assim como o algoritmo de intercalao, a implantao do quicksort por meio de uma funo
recursiva uma expresso direta do algoritmo, como mostra a Figura 317. As parties so
feitas pela funo partition, mostrada na Figura 318.
rea = rea =
f(xi).x f(xi+1).x
xi+1 xi xi+1
xi
Figura 319: reas cobertas pelas somas de Riemann pela esquerda e pela direita para no intervalo
[0,1]
A Figura 319 mostra duas formas de se aproximar do valor da integral utilizando somas das
reas de retngulos, conhecidas como soma de Riemann pela esquerda e soma de Riemann
pela direita. Podemos ver que a rea definida pela soma de Riemann pela esquerda dada por
enquanto a rea definida pela soma de Riemann pela direita dada por
rea do sub-intervalo =
x.(f(xi) + f(xi+1))/2
xi xi+1
Figura 323: Aproximao por trapzios
ou
ou
Uma funo que calcula uma integral por trapzios est mostrada na Figura 324.
Para testar esta funo, vamos calcular , cujo valor exato ns sabemos que igual
a . Com 5 intervalos, o resultado da chamada
TrapezoidalSum(sin,0,%pi,5) foi 1.9337656; com 50 intervalos (chamada
TrapezoidalSum(sin,0,%pi,50)), o valor obtido foi 1.999342.
4.4.2 Bisseo
Ns sabemos que as razes (ou zeros) de funes como um polinmio de 2 grau podem ser
encontradas por frmulas analticas, mas isto no possvel para muitas outras funes. O
mtodo da bisseo um algoritmo que serve para determinar numericamente uma raiz de
uma equao , onde uma funo contnua qualquer. Para dar incio ao
algoritmo, precisamos de dois pontos e , sendo , onde a funo assume sinais
opostos, ou seja, ou bem e , ou ento e , como
mostrado na Figura 325.
Figura 327: Intervalos em que a funo no tem sinais opostos nos extremos podem conter ou no uma raiz
Figura 328: Se a funo no for contnua, sinais opostos nas extremidades de um intervalo no garantem que ele
contenha uma raiz
O mtodo da bisseo exige portanto que seja contnua em um intervalo tal que
. De uma forma similar ao algoritmo de pesquisa binria, a cada iterao a
funo calculada no ponto mdio do intervalo, .
Figura 329: Caso em que a raiz est " esquerda" do ponto mdio do intervalo
Figura 330: Caso em que a raiz est " direita" do ponto mdio do intervalo
A Figura 331 mostra uma primeira verso da funo bissecao contendo apenas o seu
cabealho:
O primeiro parmetro formal de entrada, f, a funo da qual se deseja encontrar a
raiz;
Os parmetros a e b so os limites do intervalo, e devem ser tais que f(a)*f(b) <
0;
O parmetro tol a tolerncia, isto , um valor para o tamanho do intervalo de busca
onde a preciso desejada considerada satisfatria;
O parmetro de sada r a raiz encontrada.
Para testar a funo bissecao, ns precisamos:
de uma funo contnua,
de um intervalo onde a funo troca de sinal,
e de conhecer o valor de uma raiz nesse intervalo para que seja possvel verificar o
resultado.
b
a
Figura 332: Grfico de
O grfico da Figura 332 pode ser obtido na console do Scilab com os comandos mostrados na
Figura 334. A diretiva axesflag=5 faz com que os eixos sejam traados no ponto (0,0).
-->exec("exp_sin.sci")
-->x = linspace(0,2*%pi,101);
-->y = exp_sin(x);
-->plot2d(x,y,axesflag=5)
Figura 334: Comandos para obter o grfico da Figura 332 na console do Scilab
Com isso ns j podemos construir um programa testador para a funo bissecao, conforme
mostra a Figura 335. O programa permite experimentar com diversos valores de tolerncia,
comparando a raiz calculada com o valor de com 10 casas decimais.
clear
exec("exp_sin.sci");
exec("bissecao.sci");
tolerancia = input("\nTolerncia = ");
while tolerancia > 0
raiz = bissecao(exp_sin,2,4, tolerancia);
printf(" Raiz = %12.10f; \n Pi = %12.10f\n",raiz,%pi);
tolerancia = input("\nTolerncia = ");
end
Figura 335: O programa bissecao_teste.sce
A Figura 338 mostra o resultado de um teste da funo bissecao, onde podemos ver o efeito
da tolerncia fornecida pelo usurio sobre a preciso do clculo da raiz.
Tolerncia = 1.0e-3
Raiz = 3.1411132813;
Pi = 3.1415926536
Tolerncia = 1.0e-6
Raiz = 3.1415925026;
Pi = 3.1415926536
Tolerncia = 1.0e-10
Raiz = 3.1415926536;
Pi = 3.1415926536
Figura 338: Teste da funo bissecao
,
ou, lembrando que ,
Esta srie converge para qualquer valor de . Ns podemos ver que, a partir do termo onde
, cresce mais rapidamente que , e que o valor absoluto dos termos tende para zero
quando tende para infinito. Queremos aqui construir uma funo Scilab que calcule por
esta frmula, adicionando termos at que seu valor absoluto seja menor que uma tolerncia
fornecida pelo usurio. J temos como escrever o cabealho da funo, como mostra a Figura
339.
function y = expTaylor(x,tol)
// Calcula a soma dos termos
// da srie de Taylor at o primeiro
// termo com valor absoluto menor
// que a tolerncia tol
endfunction
Figura 339: Cabealho da funo expTaylor
exec("expTaylor.sci");
tol = input("\ntol = ");
x = input("\nx = ");
while x ~= 999
expCalc = expTaylor(x,tol);
printf("\n x exp(x) expTaylor(x) Erro")
printf ("\n%12g %15.8e %15.8e %15.8e\n", ...
x,exp(x),expCalc,exp(x)-expCalc)
x = input("\nx = ");
end
Figura 340: O programa expTaylor_teste.sce
Com isso ns chegamos forma final da funo expTaylor, mostrada na Figura 341.
function y = expTaylor(x,tol)
// Calcula a soma dos termos
// da srie de Taylor at o primeiro
// termo com valor absoluto menor
// que a tolerncia tol
Termo = 1;
y = 1;
i = 1;
while abs(Termo) >= tol
Termo = Termo * x / i;
y = y + Termo;
i = i+1;
end
endfunction
Figura 341: A funo expTaylor
Vamos primeiramente testar a funo para alguns valores positivos de x. Podemos ver na
Figura 342 que os resultados so muito bons, com diferenas 16 ordens de grandeza menores
que os valores calculados pelas duas funes.
tol = 1.0e-40
x = 1
1 2.71828183e+000 2.71828183e+000 -4.44089210e-016
x = 10
10 2.20264658e+004 2.20264658e+004 7.27595761e-012
x = 30
30 1.06864746e+013 1.06864746e+013 -3.90625000e-003
Figura 342: Resultados de testes da funo expTaylor com x positivo
Mas o teste com valores negativos nos reserva surpresas desagradveis, como mostra a Figura
343. Para x == -1, o erro inferior aos valores por 15 ordens de grandeza, muito bom. Para
x == -10, o erro 8 ordens de grandeza menor que os valores calculados; v l. J com x
== -20, o erro da mesma ordem de grandeza dos valores calculados, muito ruim. A casa cai
mesmo com x==-30, quando o erro 9 ordens de grandeza maior que o valor correto, e,
pior, o valor calculado para negativo, sendo que uma funo estritamente
positiva!
tol = 1.0e-40
x = -1
-1 3.67879441e-001 3.67879441e-001 -1.11022302e-016
x = -10
-10 4.53999298e-005 4.53999296e-005 1.39453573e-013
x = -20
-20 2.06115362e-009 5.62188447e-009 -3.56073085e-009
x = -30
-30 9.35762297e-014 -3.06681236e-005 3.06681237e-005
Figura 343: Resultados de testes da funo expTaylor com x negativo
-->eps = 1.0e-23;
-->y = 1.0e23;
-->x = y + eps;
-->x == y
ans = x igual a y bit por bit!
T
Figura 344: Exemplo de cancelamento catastrfico
A origem dos maus resultados est na aritmtica de ponto flutuante, que usa um nmero fixo
de bits para representao da mantissa. Operaes aritmticas com nmeros com grandes
diferenas de ordem de grandeza no funcionam corretamente, como mostra a Figura 344.
O valor 1.0e-23 somado a 1.0e23 no altera o seu expoente, o que natural, mas
tampouco altera a sua mantissa, que no possui bits suficientes para essa adio. O valor
somado simplesmente perdido na operao, em um efeito que conhecido por
cancelamento catastrfico.
~4.3e007
15 ordens de
grandeza maior
que o resultado
correto
Figura 345: Grfico com valores absolutos dos termos da srie de Taylor para x == -20
A Figura 345 mostra um grfico com os valores absolutos dos termos da srie de Taylor para x
== -20. O maior valor absoluto de um termo da ordem de , e o valor correto para
da ordem de . Ou seja, nas operaes aritmticas realizadas com os primeiros termos
da srie os erros de truncamento podem ser bem maiores que o resultado final, e isso o que
ocorre com o uso da funo expTaylor para o clculo de exponenciais de nmeros
negativos.
Como lio a tirar destes exemplos, voc deve ter muito cuidado ao operar com nmeros de
valores com grandes diferenas de ordem de grandeza. A aritmtica de ponto flutuante
melindrosa; use funes de bibliotecas, desenvolvidas por profissionais de clculo numrico,
sempre que possvel. Por outro lado, no se deixe levar pelo pessimismo. Programas
numricos funcionam como esperado na maior parte dos casos.
2<3 1. 2. 3.
1. 2. 3.
1<2 1. 3. 2. 1<3 1. 3. 2.
1. 3. 2.
3. 1. 2. 3<2
1. 2. 3. 3. 1. 2.
1. 3. 2. 3<1 3. 1. 2.
2. 1. 3.
?
2. 3. 1.
3. 1. 2.
1<3 2. 1. 3.
3. 2. 1. 2. 1. 3.
2. 1. 3. 2<3
2<1 2. 3. 1. 2. 3. 1.
3. 2. 1. 3<1 2. 3. 1.
3<2 3. 2. 1.
Figura 346: Uma rvore de decises para ordenao de 3 elementos.
Raiz Folhas
no tm
filhos
p=0
p=1
p=2
p=3
Figura 348: Profundidade em uma rvore
ou
Figura 350: A soma dos logaritmos dos inteiros de 1 a n a soma de Riemann pela esquerda para log(n)
Isso prova que o limite inferior para a complexidade de qualquer algoritmo de ordenao por
comparaes .
2
6
5 3 2
3
3 4
4 7 3
Figura 351: Distncias entre cidades a serem visitadas pelo caixeiro viajante
Qual o melhor roteiro, isto , qual o roteiro com a menor distncia total, partindo da
cidade 1? Na Figura 352 voc pode ver como a escolha de um roteiro influencia a distncia
total.
1 1 1
2 2 2
6 6 6
5 3 2 5 3 2 5 2
3
3 3 3
3 4 3 4 3 4
3 3 3
4 7 3 7
4 3 4 7 3
D = 19 D = 22 D = 15
Figura 352: Algumas alternativas de roteiros para o caixeiro viajante
Um exame atento nos faz perceber que o roteiro mais direita na Figura 352 , dentre todos,
o de menor custo. Descobrir o roteiro timo fica bem mais complicado quando temos mais
cidades, como na Figura 353.
1
12 9 11 2
8
9 13
10 9
8 1 12
14
15
7 12 3
15 5
12 4
11
6 12 4
6 1
3
5
Figura 353: Um problema com 8 cidades
Temos muito mais alternativas a examinar; trs exemplos esto na Figura 354. Aqui tambm a
alternativa mais direita a rota tima, fato que no fcil de se confirmar por um simples
exame do problema. Precisamos do auxlio de um computador.
Queremos construir um programa que, dado um conjunto de cidades e suas distncias,
descubra o melhor roteiro para o caixeiro viajante.
1 1 1
12 9 11 2 12 9 11 2 12 9 11 2
8 8 8
9 9 9 13
13 13
9 9 10 9
8 1 10 12 8 1 10 12 8 1 12
14 14 14
15 15 15
7 12 7 12 7 12 3
3 3
5 5 15 5
15 15
12 12 12 4
11 4 11 4 11
4 4 6 12 4
6 12 6 12 6
6 6 1 3 1
3 1 3 5
5 5
D = 81 D = 98 D = 64
Figura 354: Algumas alternativas de roteiros para o problema da Figura 353
E como fazer para gerar todas as alternativas de roteiros? Temos que gerar todas as
permutaes das cidades a serem percorridas. Para um problema com 4 cidades, as rotas a
serem examinadas so (lembrando que a cidade 1 o ponto inicial e final, e portanto faz parte
de qualquer circuito):
2 3 4
2 4 3
3 2 4
3 4 2
4 2 3
4 3 2
Ns iremos precisar de uma funo que gere as permutaes de um conjunto de nmeros,
cada nmero correspondendo a uma cidade. Vamos primeiramente definir um cabealho para
uma funo permutations (Figura 355).
Function p = permutations(A)
// gera uma matriz p onde
// cada linha uma permutao de A
endfunction
Figura 355: Cabealho da funo permutations
Precisamos agora de um algoritmo para gerar essas permutaes. O raciocnio , mais uma
vez, recursivo:
Se o vetor A de tamanho 1, ele j a nica permutao possvel;
seno, devemos separar o primeiro elemento do vetor;
gerar todas as permutaes dos elementos restantes (mesmo problema inicial, mas
com um elemento a menos), e fazer uma justaposio do elemento separado com as
permutaes obtidas;
repetir este procedimento para os demais elementos do vetor.
Como exemplo, considere o processo de gerar todas as permutaes do vetor [2 3 4]. Ns
devemos:
Separar o elemento 2, e gerar todas as permutaes do vetor [3 4]; depois, concatenar
2 s permutaes obtidas;
Separar o elemento 3, e gerar todas as permutaes do vetor [2 4]; depois, concatenar
3 s permutaes obtidas;
Finalmente, separar o elemento 4, e gerar todas as permutaes de [2 3], e depois
concatenar 4 s permutaes obtidas.
A funo permutations mostrada na Figura 356 uma implementao direta deste
algoritmo.
function p = permutations(A)
if length(A) == 1 then
p = A;
else
p = [];
for i = 1:length(A)
B = permutations(OneOut(A,i));
[nl,nc] = size(B);
for j = 1:nl
p = [p ; [A(i) B(j,:)]];
end
end
end
endfunction
function b = OneOut(A,i)
x = 1:length(A);
b = A(x ~= i);
endfunction
Figura 356: A funo permutations
Ela faz uso da funo OneOut, que implementa a operao de separar o i-simo elemento
do vetor, e que um bom exemplo de uso das possibilidades oferecidas pelo Scilab para
manipulao de matrizes apresentadas na Seo 3.2.9 (pg. 129).
J podemos dar incio ao desenvolvimento do programa principal. A Figura 357 apresenta uma
primeira verso, formada apenas por comentrios.
// L a matriz de distncias
// Gera todas as rotas possveis
// Calcula o custo de cada rota
// Seleciona a de menor custo
// Imprime o resultado
Figura 357: Primeira verso do programa CaixeiroViajante.sce
Figura 358 : Arquivo Distancias.txt com distncias entre as cidades mostradas na Figura 351
Este arquivo pode ser lido diretamente com fscanfMat. Aps a leitura, os elementos com
valor -1 devem ser substitudos por %inf. Voc pode ver este cdigo na Figura 359, onde
est destacado o comando que faz as substituies.
// L a matriz de distncias
Dist = ...
fscanfMat(uigetfile("*.txt",pwd(),"Distncias"));
// Substitui -1 por %inf
Dist(Dist==-1) = %inf;
Figura 359: Leitura do arquivo com distncias
Para gerar as rotas e calcular seus custos, vamos usar a funo permutations da Figura
356, e tambm uma funo cost, que recebe como parmetros de entrada uma matriz D de
distncias, e um vetor path, que contm os ndices das cidades que compem uma rota.
Nos trechos de cdigo mostrados na Figura 360 voc deve reparar que:
o vetor Rotas recebe todas as permutaes das cidades de 2 a n, e no de 1 a n, pois
a cidade 1 sempre o ponto de partida e de chegada.
a rota enviada (passada como parmetro real) para a funo cost o vetor formado
pela cidade 1 acrescida das cidades que compem uma linha do vetor Rotas,
acrescido novamente pela cidade 1.
exec("permutations.sci");
exec("cost.sci");
exec("OneOut.sci");
exec("SelecionaMenor.sci");
exec("PrintMatrix.sci");
// L a matriz de distncias
Dist = fscanfMat(uigetfile("*.txt",pwd(),"Distncias"));
PrintMatrix("Distncias",Dist);
// Substitui -1 por %inf
Dist(Dist==-1) = %inf;
// Obteno das rotas
[nl,nc] = size(Dist); //nl deve ser igual a nc
Rotas = permutations(2:nc);
// Calcula o custo de cada rota
[NL,NC] = size(Rotas);
for i = 1:NL
Custo(i) = cost(Dist,[1 Rotas(i,:) 1]);
if Custo(i) <> Exemplos(:,1) then
end
end
// Seleciona a de menor custo
Melhor = SelecionaMenor(Custo,1);
// Imprime a melhor rota
printf("\nA melhor rota ");
PrintMatrix("Rota",[1 Rotas(Melhor,:) 1]);
printf("com custo total = %d.",Custo(Melhor));
Figura 361: O programa CaixeiroViajante.sce
A Figura 361 mostra o programa completo, que tambm usa as funes SelecionaMenor
(Figura 303, pgina 162) e PrintMatrix (Figura 304, pgina 162). Executando este
programa com o arquivo Distancias.txt (Figura 358), ns vemos que a melhor rota [1 2 3 5
4 1] com custo total = 15, mostrada na Figura 352.
Muito bem, temos um programa que resolve o problema do caixeiro viajante. Mas ser que
com ele ns poderemos encontrar o melhor roteiro para visitar de avio todas as 27 capitais
brasileiras? melhor nem tentar. Com cidades, temos permutaes a explorar.
Para o exemplo com 5 cidades, so possibilidades, fcil. Para 8 cidades, temos
rotas a examinar, sem problemas, mas para as capitais brasileiras, so
permutaes a serem examinadas!
Figura 363: Quais objetos devem ser colocados na mochila para se obter o maior peso total sem ultrapassar a
capacidade da mochila?
100 0 1
1 100 00
1001100100100
Figura 365: Uma soluo com 7 domins
Vamos representar uma sequncia de domins por um vetor de ndices como [1 3 1 1 3 2 2],
que significa um domin do tipo 1, seguido de um domin do tipo 3, seguido de dois do tipo
1, seguido de um domin do tipo 2, seguido por dois do tipo 2.
Para resolver o problema de Post ns vamos novamente usar um algoritmo fora-bruta, que
gera todas as sequncias possveis de domins, comeando pelas menores. Se tivermos 3 tipos
de domins, as primeiras sequncias geradas so [1], [2], [3], [1 1], [1 2], [1 3], [2 1], [2 2], [2
3], [3 1], [3 2], [3 3], [1 1 1], [1 1 2], [1 1 3], [1 2 1], e assim por diante. Voc pode ver que a
gerao das sequncias pode ser feita por um processo equivalente contagem em um
sistema de base 3, sem o algarismo 0 e incluindo o algarismo 3.
exec("ReadPostProblem.sci");
exec("Sucessor.sci");
exec("strPost.sci");
exec("WritePostSolution.sci");
exec("WritePostProblem.sci");
found = %f;
seq = [];
while ~found
seq = Sucessor(seq,nTypes);
upString = strPost(Up,seq);
dnString = strPost(Down,seq);
found = upString == dnString;
if found then
WritePostSolution(seq,Up,Down);
end
end
Figura 366: O programa Post.sce
Figura 367: Tela do Bloco de Notas com um arquivo de tipos de domins para o problema de Post da Figura 364
Vamos comear pela leitura de um conjunto de tipos de domins. A Figura 367 ilustra o
formato que escolhemos para arquivos com tipos de domins que descrevem um problema de
Post.
A funo ReadPostProblem (Figura 368) faz uso da funo tokens, fornecida pelo Scilab,
que recebe um string como parmetro de entrada, e produz um vetor coluna, onde os
elementos do vetor so strings que, no string de entrada, esto separados por brancos ou
tabulaes.
function WritePostProblem(Up,Down);
printf("\nProblema de Post:\n");
[nl,nc] = size(Up);
for i = 1:nl
printf("%5s",Up(i));
end
printf("\n");
for i = 1:nl
printf("%5s",Down(i));
end
endfunction
Figura 369: A funo WritePostProblem
function s = strPost(Strs,seq)
s = "";
for i = 1:length(seq)
s = s + Strs(seq(i));
end
endfunction
Figura 370: A funo strPost
A Figura 370 mostra a funo strPost que constri a concatenao dos strings em uma
sequncia de domins.
function s = Sucessor(r,nTypes)
// retorna o sucessor da sequncia r
VaiUm = 1;
for i = length(r):-1:1
if VaiUm > 0 then
if r(i) < nTypes then
r(i) = r(i) + 1;
VaiUm = 0;
else
r(i) = 1;
end
end
end
if VaiUm == 1 then
s = [1 r];
else
s = r;
end
endfunction
Figura 371: A funo Sucessor
A funo Sucessor (Figura 371) gera, a partir de uma seqncia de domins, a seqncia
seguinte no processo de contagem. Essencialmente ela soma 1 ao nmero formado pelos
algarismos que compem a seqncia. A Figura 372 mostra alguns exemplos de uso desta
funo.
-->Sucessor([],3)
ans =
1.
-->Sucessor([2 3 1],3)
ans =
2. 3. 2.
-->Sucessor([3 3 3],3)
ans =
1. 1. 1. 1.
Figura 372: Exemplos de uso da funo Sucessor
J podemos testar o nosso programa para ver se encontramos a soluo da Figura 365.
Escolhendo como entrada o arquivo ProblemaPost.txt, vemos que o programa Post.sce
efetivamente resolve este problema, produzindo a sada mostrada na Figura 374.
Problema de Post:
100 0 1
1 100 00
Soluo: 1001100100100
1 3 1 1 3 2 2
100 1 100 100 1 0 0
1 00 1 1 00 100 100
Figura 374: Sada do programa Post.sce, alimentado com o arquivo da Figura 367.
Como voc j deve esperar, inferir desse primeiro sucesso que o nosso algoritmo resolve
qualquer problema de Post ingenuidade.
1000 01 1 00
0 0 101 001
Figura 375: A menor soluo para este problema de Post uma sequncia de 206 domins!
Usando algoritmos mais sofisticados, possvel mostrar que a menor seqncia que resolve o
problema da Figura 375 formada por 206 domins. Baseando-se em testes feitos pelo autor
destas linhas, o tempo estimado para o programa Post.sce resolver este problema com um
notebook seria de anos!
Poderamos pensar que estamos diante de um problema como o do caixeiro viajante, mas
mesmo isso otimismo. A correspondncia de Post pertence a uma classe de problemas
chamados indecidveis. Enquanto em problemas np-completos o espao de busca cresce
explosivamente com o tamanho da entrada, em problemas indecidveis o espao de busca
simplesmente ilimitado. Traduzindo para o problema de Post, o fato de no existir nenhuma
seqncia de tamanho que resolva um dado problema no quer dizer que no existam
solues de tamanho maior que .
A indecidibilidade se refere ao caso geral, e no a instncias particulares. Para algumas
instncias, como nos casos da Figura 365 e da Figura 375, pode ser possvel encontrar uma
soluo. Para outras, pode ser possvel demonstrar que no existe nenhuma soluo, como
seria o caso de um problema onde em todos os domins o string da parte superior fosse mais
longo que o da parte inferior.
10 0 001
0 001 1
Figura 376: Um problema de Post sem soluo conhecida.
Resultados tericos provam que no existe nenhum algoritmo que, para qualquer instncia de
um problema de Post, consiga decidir se existe ou no uma soluo. A Figura 376 mostra um
problema de Post para o qual no foi possvel, at hoje, nem encontrar uma soluo, e nem
tampouco provar que ele no admite nenhuma soluo.
e depois explorada com Smalltalk. Estas duas linguagens ainda sobrevivem, mas o uso
de C++ e de Java hoje muito maior.
Bancos de Dados. Bancos de dados so sistemas de armazenamento que extendem
muito o conceito de arquivos. Um SGBD (Sistema de Gerncia de Banco de Dados)
como Oracle, PostGresSQL, MySQL, SQL Server, e outros, permite a recuperao de
dados por perguntas (queries, em ingls. SQL quer dizer Standard Query Language)
como me d a lista dos alunos de engenharia civil com idade entre 18 e 20 anos que
j tenham cursado Programao de Computadores ou Clculo Numrico. SGBDs
tratam tambm do controle de concorrncia, controlando o acesso simultneo a uma
mesma base por diversos usurios, e garantindo a preservao de sua integridade.
Sistemas Reativos. So sistemas que reagem a diversos estmulos de forma a, por
exemplo, controlar um alto-forno, aumentando a combusto ao perceber uma baixa
de temperatura, e diminuindo quando a temperatura do forno est alta. Sistemas
operacionais como o Windows ou o Linux so tambm exemplos de sistemas reativos,
controlando os estmulos recebidos pelos equipamentos de entrada e sada.
Engenheiros e cientistas trabalham normalmente com sistemas reativos menores,
controlando mquinas e equipamentos de laboratrios.
Para finalizar, alguns conselhos.
O Scilab adequado para o desenvolvimento de pequenos programas voltados para
cincias e engenharias. Para programas maiores, com mais de 1000 linhas, considere o
uso de outras linguagens, com C, Fortran, C++ ou Java.
Qualquer que seja a linguagem escolhida, procure usar bibliotecas de funes
desenvolvidas por profissionais. S desenvolva o que for realmente necessrio.
Funes de boas bibliotecas tm cdigo mais robusto e mais rpido, e do tratamento
adequado a erros numricos.
Experimente sempre! Enquanto voc no estiver fazendo programas para uso em
produo, errar no machuca. Dificilmente um sistema se estraga por um erro de
programao, e a experimentao essencial para o aprendizado.
***
ndice Remissivo
%eps, 87 comparao de binrios sem sinal, 49
%pi, 87 comparador de 1 bit, 49
.sce, 91 compilador, 83, 84
abertura de um arquivo, 109 Complemento de 2, 25
ABus, 215 complexidade computacional, 146
acumulador, 60 complexidade linear, 154
ADconversion, 12 condutor perfeito, 29
lgebra Booleana, 27 console do Scilab, 85
algoritmo, 145 Construindo matrizes, 119
ALU, 61 controlled buffer, 57
ambiente Scilab, 85 converso binrio-decimal, 24
AND, 27 converses A/D, 8
Aritmtica matricial, 115 converses D/A, 8
arquivo-programa, 91 Correo, 145
rvore binria, 180 data width, 57
rvores de decises, 180 DBus, 215
ASCII, 23 Debug, 215
Assembler, 205 Demultiplexadores, 51
assembly, 205 descritor de arquivo, 109
atuadores, 13 desenvolvimento top-down, 139
barramento, 57 diretrio corrente, 91
Basic, 84 dividir para conquistar, 168
Binrios sem Sinal, 23 Dvorak, 13
bit, 7 eco, 86
bloco ento, 93 supresso do eco, 87
bloco seno, 93 Eficincia, 145
Blue Gene, 1 else, 93
bootstrap, 70 endereo, 58
bps, 14 endfunction, 129
C, 84 escopo de variveis, 130
C++, 84 Especificao, 145
cabealho da funo, 132 estouro, 41
Carta de tempo, 55 Expresses booleanas, 28
chamadas da funo, 128 expresses lgicas, 100
ciclo de instruo, 205 eye, 120
Ciclo de Micro-Instruo, 220 fatorao de nmeros inteiros, 147
Circuito para sincronizao, 214 fechamento de um arquivo, 109
circuito principal da CPU Pipoca, 212 fetch, 225
Cleve Moler, 84 flip-flop tipo D, 54
clock, 63 Flip-flops, 54
Cobertura dos 1s, 38 folhas, 180
Cobol, 84 Fortran, 83
Codificao com Deslocamento, 25 fprintfMat, 124
cdigo da instruo, 208 fscanfMat, 124
comando de atribuio, 86 funo recursiva, 137
Comandos Aninhados, 104 Funes, 127
comentrios, 92 function, 129
Referncias
Andrews, D. (n.d.). Primes R US. Retrieved from http://www.geocities.com/primes_r_us/
Burch, C. (2002). Logisim: A Graphical Tool for Designing and Simulating Logic Circuits.
Retrieved March 2009, from http://ozark.hendrix.edu/~burch/logisim/
Dijkstra, E. W. (1972). Chapter I Notes on Structured Programming. In E. W. O. J. Dahl,
Structured Programming. Eds. ACM Classic Books Series. Academic Press Ltd., London, UK, 1-
82.
Flickr. (n.d.). Retrieved Fevereiro 2010, from
http://farm4.static.flickr.com/3444/3348244651_fef16ef641.jpg
Garey, M. R., & Johnson, D. S. (1979). Computers and Intractability: A Guide to the Theory of
NP-Completeness. New York, USA: W. H. Freeman & Co.
Hollasch, S. (2005). IEEE Standard 754 Floating Point Numbers. Retrieved August 25, 2009,
from http://steve.hollasch.net/cgindex/coding/ieeefloat.html
HotHardware.com. (n.d.). Intel Core 2 Extreme QX9770 Performance Preview. Retrieved
Fevereiro 2010, from
http://hothardware.com/articles/Intel_Core_2_Extreme_QX9770_Performance_Preview/
I.Ziller, J. B. (1954). Preliminary Report: Specifications for the IBM Mathematical FORmula
TRANslating System, FORTRAN. International Business Machines, Applied Science Division.
IBM. (n.d.). IBM Archives - Personal Computer. Retrieved 2009, from http://www-
03.ibm.com/ibm/history/exhibits/pc/pc_1.html
Lohninger, H. (2006). (Vienna University of Technology) Retrieved from
http://www.vias.org/simulations/simusoft_adconversion.html
Lyon, B. (2005). The Opte Project. Retrieved August 2009, from http://opte.org/
Mathworks. (n.d.). Retrieved Fevereiro 2010, from http://www.mathworks.com/
McJones, P. (n.d.). History of FORTRAN and FORTRAN II. (Computer History Museum) Retrieved
April 2009, from Software Preservation Group:
http://www.softwarepreservation.org/projects/FORTRAN/
McKeeman, B. (n.d.). MATLAB 101 - A talk for the MIT Computer Science Department.
Retrieved Fevereiro 2010, from
http://www.cs.dartmouth.edu/~mckeeman/references/matlab101/matlab101.html
Morris, R. J. (2003). The Evolution of Storage Systems. IBM Systems Journal , 42 (2), 205-217.
Neumann, J. v. (1945). Michael D. Godfrey home page. Retrieved Maro 2010, from
http://qss.stanford.edu/~godfrey/vonNeumann/vnedvac.pdf
O'Reilly Media. (n.d.). Language Poster. Retrieved April 2009, from History of Programming
Languages: http://oreilly.com/news/languageposter_0504.html
Scilab Consortium. (n.d.). Scilab Home Page. Retrieved from http://www.scilab.org/
StatLib. (1989). StatLib - Datasets Archive. (Department of Statistics, Carnegie Mellon
University) Retrieved March 2009, from http://lib.stat.cmu.edu/datasets/
Top500. (n.d.). Top 500 supercomputers. Retrieved from http://www.top500.org
3. Bill McKeeman. MATLAB 101 -- A talk for the MIT Computer Science Department
[Internet]. 2005;[cited 2011 Mar 7 ] Available from:
http://www.cs.dartmouth.edu/~mckeeman/references/matlab101/matlab101.html
5. Home - Scilab WebSite [Internet]. [date unknown];[cited 2011 Mar 7 ] Available from:
http://www.scilab.org/
6. The Effective Teaching and Learning Network - training course and information for
teachers - TQM and Classroom Research [Internet]. [date unknown];[cited 2011 Mar 7 ]
Available from: http://www.etln.org.uk/resources/page16.html
7. IBM Archives: IBM Personal Computer [Internet]. [date unknown];[cited 2011 Mar 7 ]
Available from: http://www-03.ibm.com/ibm/history/exhibits/pc/pc_1.html
10. DIY Calculator :: Heath Robinson Rube Goldberg (HRRG) Computer [Internet]. [date
unknown];[cited 2011 Mar 11 ] Available from: http://www.diycalculator.com/popup-m-
hrrgcomp.shtml
11. Alan Turing - Wikipedia, the free encyclopedia [Internet]. [date unknown];[cited 2011 Mar
11 ] Available from: http://en.wikipedia.org/wiki/Alan_Turing
13. Legit Reviews. Intel Core i7-980X Six-Core Processor Extreme Edition Review [Internet].
[date unknown];[cited 2011 Mar 11 ] Available from:
http://www.legitreviews.com/article/1245/1/
14. Barret Lyon. The Opte Project [Internet]. [date unknown];[cited 2011 Mar 7 ] Available
from: http://opte.org/
17. Euclidean algorithm - Wikipedia, the free encyclopedia [Internet]. [date unknown];[cited
2011 Mar 8 ] Available from: http://en.wikipedia.org/wiki/Euclidean_algorithm#cite_note-
2
Considerando que queremos poder trocar com facilidade o programa que rege um
computador, a nica opo colocar programas em uma memria, ao invs de implement-
los com circuitos. O termo software, com o prefixo soft, macio, foi um neologismo criado para
se contrapor a hardware, mais duro, constitudo por circuitos concretos. Software muito
mais flexvel.
Figura 379: Um programa deve estar codificado em bits para ser carregado em alguma memria
Alguns dos primeiros computadores tinham uma memria para programas e outra para dados,
mas na quase totalidade dos computadores atuais programas e dados so armazenados na
mesma memria, seguindo a arquitetura chamada de Von Neumann, que props este arranjo
em 1945 (Neumann, 1945).
Um programa tem um carter dual, pois ele deve ao mesmo tempo:
expressar a forma com que uma pessoa um programador pensa em resolver um
problema de transformao de informao, e
poder ser executado pelo processador, isto , por um circuito digital.
Na prtica estas duas demandas podem ser atendidas da seguinte maneira. Um programa
composto por instrues de mquina, que so escritas por um programador em uma
linguagem chamada Assembler, e depois traduzidas para serem executadas por uma CPU.
Isso feito por um processo que chamamos de montagem (assembly) das instrues.
Figura 383: A coordenao da execuo de instrues na Pipoca exige registradores extras: PC (Program Counter),
IR (Instruction Register), Sinc Sada e Sinc Entrada
Um ciclo de instruo se inicia pela leitura da instruo (ou instruction fetch) a ser executada. A
instruo lida da memria, no endereo dado pelo contedo do registrador PC, e colocada
no registrador IR.
Processadores so construdos de forma tal que a prxima instruo a ser executada est
normalmente no endereo na memria subseqente ao ocupado pela instruo em execuo.
Ou seja, as instrues em princpio so executadas na mesma sequncia em que se encontram
armazenadas na memria. Instrues especiais, chamadas instrues de desvio, podem alterar
essa ordem de execuo. Desvios podem condicionais, dependendo por exemplo do resultado
de uma comparao.
Um circuito chamado unidade de controle recebe como entradas o cdigo da instruo, o
status de registradores de comparaes, um sinal de um oscilador (um clock), e se incumbe da
gerao correta dos sinais de controle correspondentes que comandam o ciclo de instruo na
CPU.
Figura 386: Uma unidade de controle e um clock so necessrios para a execuo de programas
1 Instrues
Para facilitar a programao, as instrues que constituem um programa no so estruturadas
diretamente em termos de sinais de controle o que entretanto se poderia esperar, visto que
a emisso destes sinais o efeito final necessrio para se produzir uma computao. Aes
tpicas de instrues de mquina so somar o contedo da posio X de memria ao
acumulador, ou ler um dado em pinos de entrada e colocar na posio de memria Y, com
mais significado para o programador. A emisso efetiva dos sinais de controle fica definida
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
OpCode Mode Operand
Figura 387: Formato de uma instruo da Pipoca
Ns vimos que instrues devem ser codificadas tambm em bits. A Figura 387 mostra o
formato que escolhemos para as instrues da Pipoca. Cada instruo tem 16 bits, sendo 4
para o cdigo da instruo, 2 para o modo de endereamento (que explicaremos a seguir) e 10
para um operando.
Instrues so definidas em termos de alteraes na viso que um programador tem da CPU.
O conjunto completo de instrues da Pipoca est mostrado na Tabela 17. So 11 instrues
ao todo. Como dispomos de 4 bits para o cdigo da instruo, temos ainda espao para quatro
outras instrues, que podem vir a ser implementadas em novas verses.
Tabela 17: Conjunto de instrues da Pipoca
BranchAddr16
Mnemonic
OpCode10
OpCode2
Description
Nessa tabela,
o campo Description descreve o efeito da instruo;
o campo Mnemonic contm cdigos para cada instruo, que so empregados por um
programador ao construir um programa;
o campo OpCode10 enumera as instrues e, com isso, fornece um cdigo para cada
uma delas;
o campo OpCode2 contm os mesmos valores de OpCode10, mas codificados em
binrio de 4 bits, destinados ao uso por computadores;
O campo BranchTable16 ser explicado mais tarde.
Voltando Figura 387, os dois bits do modo de endereamento modificam a interpretao do
campo de operando conforme a Tabela 18.
Memria
Supondo que em um dado instante a posio 7 da memria contenha o valor 23, e que a
posio 23 da memria contenha o valor 41, uma instruo ADD com o valor 7 codificado em
seu campo de operando ter como efeito:
Se o endereamento for imediato, somar 7 ao contedo do acumulador;
Se o endereamento for direto, somar o contedo da posio 7 da memria ao registrador
no caso, somar 23 ao acumulador;
Se o endereamento for indireto, somar o contedo da posio dada pelo contedo da
posio 7 ao acumulador no caso, somar 41 ao acumulador.
2 Programao em Assembler
Um programa executvel um mapa da memria, contendo instrues e dados codificados
em binrio. Entretanto, nenhum ser humano com sade mental consegue fazer um programa
diretamente em binrio. O processo de programao em Assembler consiste em:
preencher uma tabela com os mnemnicos das instrues, dando nomes a posies de
memria e usando esses nomes como operandos, sendo assim mais compreensvel
para humanos, e
depois, substituir esses mnemnicos e nomes de posies de memria pelos cdigos
binrios correspondentes, um processo a que damos o nome de montagem.
O programa em binrio deve ser gravado em alguma mdia hoje em dia, um arquivo,
antigamente, fitas de papel ou cartes perfurados e, no momento da execuo, ser
carregado na memria do computador. Na Pipoca, simulada no Logisim, isso equivale carga
de uma imagem na memria principal, o que possvel fazer clicando com o boto direito do
mouse sobre o componente memria. Em computadores reais so programas chamados
loaders que se incumbem de ler mdias com programas binrios e carreg-los na memria.
Um mesmo programa tem portanto trs formas:
Programa Fonte, que um texto em formato tabular, escrito e legvel por humanos;
Programa Executvel, que resulta da montagem do programa fonte, e normalmente
um arquivo com uma imagem da memria. No Logisim, um programa executvel um
arquivo ASCII onde cada linha representa uma palavra da memria, codificada em
hexadecimal, e
Programa em Execuo, que um conjunto de palavras na memria principal.
A Tabela 19 mostra o cdigo fonte do programa SumX, cuja funcionalidade consiste em somar
os valores na memria entre o endereo X e o endereo XEND. Ns vemos ali que o cdigo das
instrues (do endereo 0 ao endereo 14) est junto com os dados (do endereo 15 ao 21).
Esses dados consistem no vetor X, que ocupa as posies de 15 a 19, e em duas outras
posies: SUM, que ir conter a soma desejada, e P, que ser utilizado para enderear a
parcela de X que somada em cada passo da execuo do programa. Na Pipoca, o programa
comea a ser executado pela instruo na posio 0 da memria.
O programa SumX tem:
Uma etapa de inicializao das variveis (posies de memria) SUM e P, formada
pelas instrues nos endereos de 0 a 3, e que atribui o valor inicial 0 para SUM, e
coloca em P o endereo X.
Um loop composto pelas instrues colocadas entre o endereo 4 e o endereo 12. Em
cada passo deste loop uma das parcelas adicionada a SUM, e o endereo
armazenado em P incrementado. Ao fim do passo P comparado com XEND e,
dependendo do resultado, o loop repetido ou o programa passa para a sua fase final.
Uma etapa de finalizao, onde o resultado da soma encaminhado para a sada e o
programa pra.
XEND
SUM
P
Figura 389: Uso das variveis SUM e P no programa SumX.
A converso para binrio de uma linha de cdigo como LOAD 1 SUM se faz pelas etapas
abaixo, ilustradas na Figura 390:
Na Tabela 17 vemos que o cdigo da instruo LOAD 1000.
O modo de endereamento codificado em binrio com 2 bits 01.
Olhando o programa na Tabela 19, ns vemos que SUM o nome (label) dado
posio 20 de memria, que, em binrio de 10 bits, 0000010100.
A converso completa resulta da concatenao (justaposio) desses trs binrios,
resultando em 1000010000010100 ou, em hexadecimal, 8414.
Como voc pode ter percebido, a traduo da tabela-programa para binrio uma tarefa
insana. Mas essa tarefa s foi feita manualmente pelos pioneiros da computao com , pelos
parmetros atuais, enormes custos de verificao e baixssima produtividade dos
programadores. Mas cedo se percebeu que computadores eram muito bons para ... auxiliar a
programao de computadores! Um montador (um assembler) um programa que l uma
tabela-programa, e gera imagens binrias a serem carregadas nas memrias, automatizando o
processo ilustrado na Figura 390.
Figura 391: O programa SumX, como um arquivo de imagem de memria do Logisim e carregado na memria
A Pipoca um circuito simulado no Logisim, onde mapas de memria podem ser carregados
clicando sobre a memria com o boto direito do mouse e escolhendo a opo Load Image,
que abre um dilogo para escolha de um arquivo como o mostrado na Figura 391. Arquivos
como esse podem ser produzidos usando a planilha Pipoca.xls, disponvel no site do curso, e
aqui utilizada como um assembler.
Complicado? Sem dvida, mas vamos por partes; mingau quente se come pelas beiradas.
Primeiramente, voc deve reparar que neste circuito o principal complicador a unidade de
controle, o retngulo vertical na parte inferior do circuito. Para ali vo muitos fios, e dali saem
outros tantos. Isto no de se estranhar, posto que a funo da unidade de controle , como
dissemos, levantar os sinais de controle na sequncia e tempos adequados para a implantao
dos fluxos de dados que implementam as instrues de mquina. Como exemplos, esto
destacados na Figura 392 cabeamentos para o sinal de clock do acumulador (em azul), para a
tomada do barramento de dados pelo registrador Input (em vermelho) e para o campo
operando da instruo (em marrom). O conjunto completo de entradas e sadas da unidade de
controle est mostrado na Figura 393.
Estado da
CPU
Propulsor
21 sinais de
controle
O circuito principal da CPU Pipoca tem ainda circuitos auxiliares para sincronizao de entrada
e sada, colocados na parte superior do diagrama, e um circuito para depurao (debug) de
programas, no canto inferior direito que, bloqueando o sinal de clock, permite que a execuo
de um programa se interrompa ao trmino de cada instruo executada.
Flip-flop
Sinal acionado Set/Reset
pelo dispositivo
de entrada
Sinal acionado
pela Unidade Vai para a
de Controle Unidade de
Controle
O circuito mostrado na Figura 394 realiza a sincronizao da CPU com o (nico, na Pipoca)
dispositivo de entrada. A sincronizao necessria porque, com a execuo automtica e
incessante de instrues pela CPU, existe tanto a possibilidade de captura de dados nos pinos
de entrada antes que estejam prontos, como a de captura repetida de um mesmo dado de
entrada, como ainda a de mudana de dados pelo dispositivo de entrada antes de serem lidos
pela CPU. O protocolo seguido pela CPU e pelo dispositivo prescreve as seguintes regras:
Somente o dispositivo de entrada aciona o sinal SetInFull, e somente a CPU aciona o
sinal SetInEmpty;
O dispositivo de entrada somente aciona SetInFull quando o dado de entrada est
pronto e InFull = 0, e a CPU (atravs da Unidade de Controle) somente aciona
SetInEmpty quando InFull = 1 (ou InEmpty = 0), o que feito aps a leitura dos dados
de entrada;
O circuito inicializado com InFull = 0.
O circuito de sincronizao com o dispositivo de sada similar a este.
Na Pipoca, as instrues INPUT e OUTPUT exigem interveno do usurio, que deve usar a
ferramenta de manipulao do Logisim para escolher valores de entrada e tambm para
sincronizar dispositivos externos, apertando convenientemente os botes SetInFull(para
avisar que um valor de entrada est pronto para ser lido) e SetOutEmpty(para avisar que um
valor colocado anteriormente no registrador Output j foi consumido).
Programas podem ser executados instruo por instruo, o que muito til para a depurao
(debug) de erros. Para isto, preciso colocar o valor 1 na entrada Debug, e apertar o boto
Run a cada vez que uma nova instruo carregada no registrador de instruo.
Se retirarmos a Unidade de Controle da CPU Pipoca, retornando emisso manual dos sinais
de controle, e se retirarmos tambm os circuitos de sincronizo de entrada e sada, teremos
um circuito como o da Figura 395. Comparando com o circuito da Figura 111 voc pode
observar que:
foi acrescentado um registrador de instrues, o IR (Instruction Register) que tem a
funo de armazenar a instruo em execuo num dado instante;
temos um barramento de endereos, o ABus, alm do barramento de dados DBus;
com a entrada ligada ao barramento de dados , e com a sada ligada ao barramento de
endereos, ns vemos o registrador PC (Program Counter), que armazena o endereo
da prxima instruo a ser executada; ns veremos adiante a lgica de funcionamento
do PC;
temos tambm conjuntos de leds ligados a decodificadores que no tm funo na
lgica do circuito, mas nos ajudam a visualizar qual instruo est em execuo e qual
o modo de endereamento empregado na instruo corrente.
Registrador de
Instrues
ABus
Contador de
Programa DBus
5 O Contador de Programa
Outro subcircuito da CPU Pipoca o contador de programa, mostrado na Figura 396.
6 A Unidade de Controle
A Figura 397 ilustra a funo da unidade de controle, que pode ser vista com mais detalhes no
circuito da Figura 393. Para cumprir este papel a unidade de controle da Pipoca possui como
principais componentes:
um circuito Timing que fornece os sinais de tempo que conduzem a seqncia de
eventos na unidade de controle,
uma memria ROM (Read Only Memory) que contm uma tabela de desvios, a Branch
Table, cuja funo explicaremos a seguir,
A unidade de controle utiliza uma tcnica conhecida como microprogramao para produzir os
sinais de controle que, emitidos nos momentos adequados para barramentos, registradores e
memria, executam efetivamente os fluxos de dados que correspondem s instrues.
13 1101
Estes cdigos podem ser usados em
14 1110
novas microinstrues
15 1111
Instrues podem ter etapas comuns em sua execuo, como a obteno do operando
conforme o modo de endereamento. O micro-cdigo destas etapas reaproveitado usando a
micro-instrues jsr (jump to subroutine), que desvia para o endereo dado por seu operando,
e armazena o endereo atual acrescido de 1 no registrador Return Address, e a micro-
instruo return, que desvia para o endereo armazenado no registrador Return Address.
O circuito da unidade de controle pode ser visto na Figura 401, onde se pode destacar:
as entradas
o Opcode, com o cdigo da instruo corrente,
o Mode, com o modo de endereamento,
o In Empty, Out Full, com o estado dos registradores de sincronizao de entrada
e sada,
ROM
Microprograma
Timing
Figura 401: A unidade de controle
7 O Ciclo de Micro-Instruo
Um ciclo de instruo na verdade implementado por diversos ciclos de micro-instruo, que,
de forma similar aos ciclos de instruo, so compostos por etapas de leitura e de execuo de
micro-instrues que se alternam indefinidamente.
O circuito Timing est mostrado na Figura 407, sendo similar ao circuito da Figura 115.
Micro-programa
Branch Table
ADD 0 18
COMPARE 1 1C
HALT 2 45
INPUT 3 20 18
JMP 4 27 Micro-instrues
JMPEQ 5 2B para ADD
JMPGT 6 2D
JMPLT 7 2F 1C
LOAD 8 31 Micro-instrues
OUTPUT 9 36 para COMPARE
STORE 10 3B
SUB 11 41
45
Micro-instrues
para HALT
...
Figura 412: A Branch Table e o micro-programa
8 O Micro-Programa
Operand->DBus
Comments
mOperand
RAM->DBus
MAR->Abus
SetInEmpty
New Signal
New Signal
ACC->Dbus
Addr(HEX)
SetOutFull
DR->Dbus
ACC Clear
PC->ABus
Comp Clk
In->DBus
PC Force
Subtract
RAM Clk
MAR Clk
Address
ACC Clk
Out Clk
Label
DR Clk
PC Clk
In Clk
IR Clk
Type
A Figura 414 mostra o micro-cdigo que implementa a leitura (fetch) de uma nova instruo.
Este micro-cdigo executado ao fim de cada instruo; todas as instrues sempre terminam
pela micro-instruo jmp Fetch. Repare que a ltima micro-instruo de Fetch jmpNext que,
como vimos, desvia para a posio apontada pela sada da ROM Branch Table.
m-Instruction
Operand->DBus
Comments
mOperand
RAM->DBus
MAR->Abus
SetInEmpty
New Signal
New Signal
ACC->Dbus
Addr(HEX)
SetOutFull
DR->Dbus
ACC Clear
PC->ABus
Comp Clk
In->DBus
PC Force
Subtract
RAM Clk
MAR Clk
Address
ACC Clk
Out Clk
Label
DR Clk
PC Clk
In Clk
IR Clk
Type
18 24 ADD jsr GetOperand 1 Resolve endereamento; operando efetivo no DR
00 0 Fetch 0 1 Sada do PC vai para Abus
19 25 0 1 Sada do DR vai para Dbus
01 1 0 1 1 Sada da RAM vai para Dbus
1A 26 0 1 1 ACC copia sada da ALU
02 2 0 1 1 1 IR copia o Dbus
1B 27 jmp Fetch 1 Fetch da prxima instruo
03 3 0 1 PC avana
04 4 jmpNext 1 Inicia a execuo da instruo armazenada no IR
41 65 SUB jsr GetOperand 1 Resolve endereamento; operando efetivo no DR
42 66 0 1 1 Sada do DR vai para Dbus; pino Subtract da ALU = 1
43 67 0 1 1 1 ACC copia a sada da ALU (=ACC - Dbus)
44 68 jmp Fetch 1 Fetch da prxima instruo
Na Figura 415 ns vemos o micro-cdigo das micro-instrues ADD e SUB. Ele se inicia com a
micro-instruo jsr GetOperand; o micro-cdigo de GetOperand (Figura 416) se encarrega de
resolver o modo de endereamento, colocando o operando efetivo da instruo no registrador
DR.
Operand->DBus
Comments
mOperand
RAM->DBus
MAR->Abus
SetInEmpty
New Signal
New Signal
ACC->Dbus
Addr(HEX)
SetOutFull
DR->Dbus
ACC Clear
PC->ABus
Comp Clk
In->DBus
PC Force
Subtract
RAM Clk
MAR Clk
Address
ACC Clk
Out Clk
Label
DR Clk
PC Clk
In Clk
IR Clk
Type
00
05 0
5 Fetch
GetOperand jmpIMMEDIATE Immediate 0
1 1 Sada do PC vai para Abus
01
06 1
6 jmpDIRECT Direct 0
1 1 1 Sada dapara
Desvia RAM vai para Dbus apropriadas
micro-instrues
02
07 2
7 jmpINDIRECT Indirect 0
1 1 1 1 IR copia o Dbus
03
08 3
8 error GetOperand 0
1 1 PC avana
Modo de endereamento inexistente??!!
04
09 4
9 Immediate jmpNext 1
0 1 Inicia
O a execuo
operando da instruo
da instruo armazenada
vai para o Dbus no IR
0A 10 0 1 1 DR copia o Dbus
0B 11 return 1 Retorna
0C 12 Direct 0 1 O operando da instruo vai para o Dbus
0D 13 0 1 1 1 MAR copia o Dbus; sada do MAR vai para o Abus
0E 14 0 1 1 Sada da RAM vai para Dbus
0F 15 0 1 1 1 DR copia o Dbus
10 16 return 1 Retorna
11 17 Indirect 0 1 O operando da instruo vai para o Dbus
12 18 0 1 1 1 MAR copia o Dbus; sada do MAR vai para o Abus
13 19 0 1 1 Sada da RAM vai para Dbus
14 20 0 1 1 1 MAR copia o Dbus; sada do MAR vai para o Abus
15 21 0 1 1 Sada da RAM vai para Dbus
16 22 0 1 1 1 DR copia o Dbus
17 23 return 1 Retorna
Operand->DBus
Comments
mOperand
RAM->DBus
MAR->Abus
SetInEmpty
New Signal
New Signal
ACC->Dbus
Addr(HEX)
SetOutFull
DR->Dbus
ACC Clear
PC->ABus
Comp Clk
In->DBus
PC Force
Subtract
RAM Clk
MAR Clk
Address
ACC Clk
Out Clk
Label
DR Clk
PC Clk
In Clk
IR Clk
Type
00
27 0 Fetch
39 JMP jsr GetOperand 0
1 1 Sada do endereamento;
Resolve PC vai para Abus operando efetivo no DR
01
28 1
40 0 1 1 1 da RAM
1 Sada do DR vaivaipara
para Dbusfora desvio no PC
Dbus;
02
29 2
41 0 1 1 1 1 1 IR copia
1 PC copiaoDbus
Dbus
03
2A 3
42 jmp Fetch 0
1 1 PC avana
Fetch da prxima instruo
04
2B 4 JMPEQ
43 jmpNext
jmpEQ JMP 1 Inicia a condicional
Desvio execuo daparainstruo
JMP armazenada no IR
2C 44 jmp Fetch 1 Fetch da prxima instruo
2D 45 JMPGT jmpGT JMP 1 Desvio condicional para JMP
2E 46 jmp Fetch 1 Fetch da prxima instruo
2F 47 JMPLT jmpLT JMP 1 Desvio condicional para JMP
30 48 jmp Fetch 1 Fetch da prxima instruo
O micro-cdigo para as instrues de desvio est mostrado na Figura 417. Repare que o micro-
cdigo das instrues de desvio condicional se inicia pelas micro-instrues de desvio
condicional correspondentes. Se a condio de desvio no estiver satisfeita, nada acontece e a
micro-instruo jmp Fetch executada para a leitura da prxima instruo.
Operand->DBus
mOperand Comments
RAM->DBus
MAR->Abus
SetInEmpty
New Signal
New Signal
ACC->Dbus
Addr(HEX)
SetOutFull
DR->Dbus
ACC Clear
PC->ABus
Comp Clk
In->DBus
PC Force
Subtract
RAM Clk
MAR Clk
Address
ACC Clk
Out Clk
Label
DR Clk
PC Clk
In Clk
IR Clk
Type
00
20 0 INPUT
32 Fetch jsr GetOperand 0
1 1 Sada do endereamento;
Resolve PC vai para Abus operando efetivo no DR
01
21 1 InLoop
33 jmpInEmpty InLoop 0
1 1 1 Sada daInEmpty
Espera RAM vai= para
0 Dbus
02
22 2
34 0 1 1 1 IR copia
1 Sada dooDRDbus
vai para Dbus
03
23 3
35 0 1 1 1 PC avana
1 MAR copia o Dbus; sada do MAR vai para o Abus
04
24 4
36 jmpNext 1
0 1 1 1 Inicia
In a execuo
copia a entrada;dasada
instruo armazenada
do In vai para Dbusno IR
25 37 0 1 1 1 1 Zera o FF InEmpty; RAM copia o Dbus
26 38 jmp Fetch 1 Fetch da prxima instruo
Na Figura 418 ns vemos o micro-cdigo para as instrues INPUT e OUTPUT que, logo aps a
obteno do operando, executam um loop de espera composto por uma nica micro-
instruo, que executada repetidamente (atravs de um desvio condicional para ela mesma)
at que a condio de sincronizao de entrada ou de sada esteja satisfeita.
Operand->DBus
Comments
mOperand
RAM->DBus
MAR->Abus
SetInEmpty
New Signal
New Signal
ACC->Dbus
Addr(HEX)
SetOutFull
DR->Dbus
ACC Clear
PC->ABus
Comp Clk
In->DBus
PC Force
Subtract
RAM Clk
MAR Clk
Address
ACC Clk
Out Clk
Label
DR Clk
PC Clk
In Clk
IR Clk
Type
00
31 0 LOAD
49 Fetch 0 1 1 Sadaodo
Zera PC vai para Abus
ACC
01
32 1
50 jsr GetOperand 0
1 1 1 Sada da endereamento;
Resolve RAM vai para Dbus operando efetivo no DR
02
33 2
51 0 1 1 1 IR copia
1 Sada dooDRDbus
vai para Dbus
03
34 3
52 0 1 1 PC avana
1 ACC copia sua entrada (= 0 + Dbus)
04
35 4
53 jmpNext
jmp Fetch 1 Inicia adaexecuo
Fetch prxima da instruo armazenada no IR
instruo
Operand->DBus
Comments
mOperand
RAM->DBus
MAR->Abus
SetInEmpty
New Signal
New Signal
ACC->Dbus
Addr(HEX)
SetOutFull
DR->Dbus
ACC Clear
PC->ABus
Comp Clk
In->DBus
PC Force
Subtract
RAM Clk
MAR Clk
Address
ACC Clk
Out Clk
Label
DR Clk
PC Clk
In Clk
IR Clk
Type
A instruo HALT implantada por uma micro-instruo de desvio incondicional para ela
mesma, o que coloca a CPU em um loop infinito, e para o processamento.
9 A Planilha Pipoca.xls
Para funcionar a Pipoca depende de ter preenchidas suas memrias RAM e ROM, o que pode
ser feito no Logisim atravs da carga de arquivos com mapas de memria. Mas como fazer
para obter mapas que correspondem a uma inteno do projetista de instrues ou do
programador? Sua codificao direta bit por bit tarefa insana. O arquivo Pipoca.xls serve
exatamente para isto, cumprindo as funes de assembler e de micro-assembler, como
descrevemos nas prximas sees. Este arquivo contm as planilhas Microinstructions,
Microprogram, Instructions, SumX, ReadX, SearchX e Aux.
A planilha Microinstructions pode ser vista na Figura 421, e contm em cada linha um
mnemnico da micro-instruo, seu cdigo em decimal e binrio, e uma descrio. Ali tambm
pode ser vista a nica frmula utilizada, que utiliza a funo Excel DEC2BIN para converter um
nmero decimal para binrio.
coluna Addr(Hex) obviamente sua converso para hexadecimal, muito teis para
acompanhamento da execuo de um programa no Logisim.
Colunas Label, m-Instruction e Operand. nessas colunas que a parte de controle do
microprograma definida. Para microinstrues de sinais estes campos devem ser mantidos
vazios.
Coluna Type. Essa coluna contm 0 se a microinstruo for de controle, e 1 se for de sinais,
valor calculado por uma frmula que simplesmente verifica se a coluna m-Instruction da
mesma linha est vazia.
Colunas Signals. So os sinais que a unidade de controle deve enviar CPU quando a
microinstruo for do tipo Signal. O micro-programador deve colocar 1s nas posies
correspondentes aos sinais desejados.
Coluna mOpCode(DEC). um campo calculado que tem o valor 0 se o campo m-Instruction
estiver vazio na linha, e seno, o cdigo decimal da microinstruo obtida por pesquisa por seu
mnemnico na planilha Microinstruction.
Coluna Operand(DEC). um campo calculado que tem o valor 0 se o campo Operand estiver
vazio na linha, e seno, o valor da coluna Address na linha onde o valor na Coluna Label igual
ao campo Operand.
Colunas Bin2Dec Conversion. Estas colunas fazem a converso para decimal de cada bit nas
colunas Type e Signals, multiplicando o bit pela potncia de 2 correspondente sua posio na
microinstruo.
Coluna Microinstruction Word(DEC). Esta coluna contm o valor em decimal da palavra de 24
bits contendo a microinstruo. Para compreender sua frmula de clculo preciso examinar
o formato das microinstrues, mostrado na Figura 400.
Figura 424: Clculo dos endereos - as setas destacam a clula C3 e sua frmula
Para obter o mapa de memria preciso agora colocar frmulas para calcular o valor de cada
palavra neste mapa. Para isso, copie as colunas OpCode10, Operand10, Word10 e Word16 da
primeira linha do programa SomaX, e cole somente as frmulas nas mesmas colunas da
primeira linha do seu novo programa. Depois, selecione as clulas com as frmulas no novo
programa, copie e cole nas linhas restantes nestas colunas, para obter a planilha completa
mostrada na Figura 425.
que diz ao Excel para colocar 0 se o campo de cdigo de instruo (E2) estiver vazio e,
seno, efetuar uma pesquisa na coluna B da planilha Instructions procurando o cdigo
da instruo (na coluna E2), obtendo assim seu cdigo decimal, que est na coluna C
desta planilha.
Para a coluna Operand10, a frmula para a clula I2
I2 =IF(ISBLANK(G2);0;IF(ISNUMBER(G2);G2;INDEX(C$1:C$36;MATCH(G2;A$1:A$36;0);1)))
dizendo ao Excel para colocar 0 se o campo de operando (G2) estiver vazio e, seno, se
o operando for um nmero, colocar este nmero diretamente; se o operando for uma
referncia, pesquisar pelo operando na coluna de labels (A), obtendo o valor do
endereo correspondente.
Para a coluna Word10, a frmula para a clula J2
J2 = H2*2^12+F2*2^10+I2
Para obter um arquivo com o mapa de memria que pode ser lido pelo Logisim,
use o Bloco de Notas para criar um arquivo SearchTable.txt, e digite v2.0 raw em sua
primeira linha;
depois, copie todos os valores na coluna Word16 da planilha com o programa, e cole
no Bloco de Notas, a partir da segunda linha. A Figura 426 mostra a janela do Bloco de
Notas com o programa executvel.
Salve o arquivo; seu programa estar pronto para ser executado.