[[cap_sistemas_numeracao]] == Sistemas de numeração :cap: cap3 .Objetivos do capítulo ____________________ Ao final deste capítulo você deverá ser capaz de: * Entender a origem dos sistemas de numeração na história * Explicar o funcionamento do sistema de numeração binário * Ser capaz de efetuar operações da aritmética e lógica binária * Compreender como a lógica binária permite criar operações mais complexas no computador ____________________ Um numeral é um símbolo ou grupo de símbolos que representa um número em um determinado instante da história humana. Tem-se que, numa determinada escrita ou época, os numerais diferenciaram-se dos números do mesmo modo que as palavras se diferenciaram das coisas a que se referem. Os símbolos "11", "onze" e "XI" (onze em latim) são numerais diferentes, representativos do mesmo número, apenas escrito em idiomas e épocas diferentes. Este capítulo debruça-se sobre os vários aspectos dos sistemas de numerais. Entraremos em mais detalhes sobre o sistema de numeração binária devido a sua utilização nos computadores, permitindo assim, que o mesmo realize pequenas operações aritméticas que servirão como base para grandes operações como busca, ordenação e indexação de informação entre outras operações comuns do dia a dia. === Noções de Sistema de Numeração (((Sistema de Numeração))) Há milhares de anos o modo de vida era muito diferente do atual. Os homens primitivos não tinham necessidade de contar. Eles não compravam, não vendiam, portanto não usavam dinheiro. Com o passar dos anos, os costumes foram mudando e o homem passou a cultivar a terra, a criar animais, a construir casas e a comercializar. Com isso, surgiu a necessidade de contar. A vida foi tornando-se cada vez mais complexa. Surgiram as primeiras aldeias que, lentamente, foram crescendo, tornando-se cidades. Algumas cidades se desenvolveram, dando origem às grandes civilizações. Com o progresso e o alto grau de organização das antigas civilizações, a necessidade de aprimorar os processos de contagem e seus registros tornou-se fundamental. Foram criados, então, símbolos e regras originando assim os diferentes sistemas de numeração. ==== Sistema de numeração Egípcio (3000 a.C.) Um dos primeiros sistemas de numeração que temos conhecimento é o egípcio, que foi desenvolvido pelas civilizações que viviam no vale do Rio Nilo, ao nordeste da África. Observem, na <>, os símbolos e a representação de alguns números nesse sistema de numeração. [[sistema_egipcio]] .Sistema de Numeração Egípcio image::images/{cap}/sistema_egipicio.eps[scaledwidth="70%"] Este sistema adota o princípio aditivo, ou seja, os símbolos possuem seus respectivos valores individuais e juntos passam a formar novos valores pela simples adição destes. ==== Sistema de numeração Babilônico (2000 a.C.) Os babilônios viviam na Mesopotâmia, nos vales dos rios Tigres e Eufrates, na Ásia. Esta região é ocupada atualmente pelo Iraque. Na escrita dos números, o sistema de numeração dos babilônios se parecia muito com o sistema de numeração desenvolvido pelos egípcios, ambos eram aditivos. Observe, na <>, os símbolos e a representação de alguns números, de 7 a 59, nesse sistema de numeração. [[fig_sistema_babilonico]] .Sistema de Numeração Babilônico image::images/{cap}/sistema_babilonico.eps[scaledwidth="70%"] [NOTE] ================== Agora é com você. Qual seria o valor que cada símbolo babilônico, seguindo os exemplos da <>? image:images/{cap}/um_babilonico.eps[] = ? image:images/{cap}/dez_babilonico.eps[] = ? ================== ==== Sistema de numeração Romano O sistema de numeração romano, apesar das dificuldades operatórias que apresentava, foi utilizado na Europa durante muitos séculos. Esse sistema de numeração foi desenvolvido pela civilização romana, cuja sede era a cidade de Roma, situada na Itália. Ainda hoje, utilizamos esse sistema de numeração em algumas situações, tais como: - na designação de papas e reis; - na designação de séculos e datas; - na indicação de capítulos e volumes de livros; - nos mostradores de alguns relógios, etc. Com o passar dos anos, o sistema de numeração romano (<>) sofreu um longo processo de evolução. Inicialmente, os romanos utilizavam apenas o principio aditivo, sendo que um mesmo símbolo podia ser repetido até, no máximo, quatro vezes. Posteriormente, eles evoluíram este sistema, passando a utilizar também o princípio subtrativo, além de permitir a repetição de um mesmo símbolo, no máximo, três vezes. [[sistema_romano]] .Sistema de Numeração Romano image::images/{cap}/sistema_romano.eps[scaledwidth="60%"] ==== Sistema de numeração Indo-Arábico Os hindus, que viviam no vale do Rio Indo, onde hoje é o Paquistão, conseguiram desenvolver um sistema de numeração que reunia as diferentes características dos antigos sistemas. Tratava-se de um sistema posicional decimal. Posicional porque um mesmo símbolo representava valores diferentes dependendo da posição ocupada, e decimal porque era utilizado um agrupamento de dez símbolos. Esse sistema posicional decimal, criado pelos hindus, corresponde ao nosso atual sistema de numeração, já estudado por você nas séries do ensino fundamental. Por terem sido os árabes os responsáveis pela divulgação desse sistema. Ele ficou conhecido como sistema de numeração indo-arábico. Os dez símbolos, utilizados para representar os números, denominam-se algarismos indo-arábicos. São eles: [frame='none', cols="^,^,^,^,^,^,^,^,^,^"] |==== | 0 | 1| 2| 3| 4| 5| 6| 7| 8| 9 |==== [TIP] ========== Veja, na <>footnote::[Fonte: http://www.programandoomundo.com/Sistema%20Indo-Arabico.htm.], as principais mudanças ocorridas nos símbolos indo-arábicos, ao longo do tempo.   [[fig_sistema_indo_arabico]] .Sistema de numeração Indo-Arábico image::images/{cap}/sistema_arabico.eps[scaledwidth="70%"] Observe que, inicialmente, os hindus não utilizavam o zero. A criação de um símbolo para o *nada*, ou seja, o zero, foi uma das grandes invenções dos hindus. ========== === Sistema de Numeração Posicional O método de numeração de quantidades ao qual estamos acostumados, utiliza um sistema de numeração posicional. Isto significa que a posição ocupada por cada algarismo em um número altera seu valor de uma potência de 10 (na base 10) para cada casa à esquerda. Por exemplo: No sistema decimal (base 10), no número 125 o algarismo 1 representa 100 (uma centena ou 10^2^), o 2 representa 20 (duas dezenas ou 2 x 10^1^), o 5 representa 5 mesmo (5 unidades ou 5x10^0^). Assim, em nossa notação: ____ 125 = 1×10^2^ + 2×10^1^ + 5×10^0^ ____ ==== Base de um Sistema de Numeração (((Sistema de Numeração))) A base de um sistema é a quantidade de algarismos disponíveis na representação. A base 10 é hoje a mais usualmente empregada, embora não seja a única utilizada. No comércio pedimos uma dúzia de rosas (base 12) e marcamos o tempo em minutos e segundos (base 60). Quando lidamos com computadores, é muito comum e conveniente o uso de outras bases, as mais importantes são a binária (base 2), octal (base 8) e hexadecimal (base 16). Um sistema numérico de base k precisa de k símbolos diferentes para representar seus dígitos de 0 a k-1. Os números decimais são formados a partir de 10 dígitos decimais: (((base decimal))) ____ `0 1 2 3 4 5 6 7 8 9` ____ Já os números na base binária são representados a partir de dois dígitos: (((base binária))) ____ `0 1` ____ O octal necessita de oito: (((base octal))) ____ `0 1 2 3 4 5 6 7` ____ No caso de números hexadecimais, são necessários 16 algarismos. Portanto, serão mais 6 símbolos além dos dez algarismos arábicos. Em geral, usam-se as letras maiúsculas de A a F: ____ `0 1 2 3 4 5 6 7 8 9 A B C D E F` _____ A representação 318~10~ (base 10), significa: ____ 318~10~ = 3×10^2^ + 1×10^1^ + 8×10^0^ ____ Generalizando, representamos uma quantidade N qualquer, numa dada base b, com um número tal como segue: ____ N~b~ = a~0~ × b^n^ + a~1~ × b^n-1^ + ... + a~n~ × b^0^ ____ Abaixo, o número 35 será expresso nas bases elencadas acima: (((Decimal)))(((Binário)))(((Octal)))(((Hexadecimal))) Decimal:: 35 = 3×10^1^ + 5×10^0^ = 30 + 5 = 35~10~ Binário:: 35 = 1×2^5^ + 0×2^4^ + 0×2^3^ + 0×2^2^ + 1×2^1^ + 1×2^0^ = 32 + 0 + 0 + 0 + 2 + 1 = 100011~2~ Octal:: 35 = 4×8^1^ + 3×8^0^ = 32 + 3 = 43~8~ Hexadecimal:: 35 = 2×16^1^ + 3×16^0^ = 32 + 3 = 23~16~ [NOTE] ==== Usualmente *bytes* são representados utilizando o sistema *hexadecimal*, pois eles são mais fáceis de manipular por programadores. Por exemplo, a sequência de bits `0010 0011` que corresponde ao número 35~10~, é expressa por `0x23` em hexadecimal. Nas linguagens de programação os números *hexadecimais* costumam ser representados com o prefixo `0x` e os octais com o prefixo `0`. Portando `23` representa o número 23, enquanto `0x23` é um valor *hexadecimal* que corresponde ao decimal 35 e `023` é um valor *octal* que corresponde ao decimal 19. ==== === Conversões entre bases Nesta seção iremos analisar as regras gerais para converter números entre duas bases quaisquer. ==== Conversões entre as bases 2, 8 e 16 As conversões mais simples são as que envolvem bases que são potências entre si. Vamos exemplificar com a conversão entre a base 2 e a base 8. Como 2^3^ = 8, então a conversão funciona da seguinte forma: separando os algarismos de um número binário (base 2) em grupos de três algarismos (começando sempre da direita para a esquerda) e convertendo cada grupo de três algarismos para seu equivalente em octal, teremos a representação do número em octal. Por exemplo: ____ 10101001~2~ = 010 . 101 . 001~2~ ____ Olhando a tabela de conversão direta temos: (((Octal))) .Conversão direta de binário para octal e vice-versa [width="50%", frame="none", grid="all", cols="^1,^1", options="header"] |================================= | Binário | Octal | 000 | 0 | 001 | 1 | 010 | 2 | 011 | 3 | 100 | 4 | 101 | 5 | 110 | 6 | 111 | 7 |================================= Logo: [cols="^,^,^,^", frame="none"] |============== | 010~2~ = 2~8~ | 101~2~ = 5~8~ | 001~2~ = 1~8~ | 10101001~2~ = 251~8~ |============== Vamos agora exemplificar com uma conversão entre as bases 2 e 16. Como 2^4^ = 16, seguindo o processo anterior, basta separarmos em grupos de quatro algarismos e converter cada grupo seguindo a <>. Por exemplo: ____ 11010101101~2~ = 0110 . 1010 . 1101~2~ ____ Olhando a tabela de conversão direta temos: (((Hexadecimal))) [[tabela_binario_hexa]] .Conversão direta de binário para hexadecimal e vice-versa. [width="70%", frame="none", grid="all", cols="^1,^1,^1,^1", options="header"] |================================= | Binário | Hexadecimal | Binário | Hexadecimal | 0000 | 0 | 1000 | 8 | 0001 | 1 | 1001 | 9 | 0010 | 2 | 1010 | A | 0011 | 3 | 1011 | B | 0100 | 4 | 1100 | C | 0101 | 5 | 1101 | D | 0110 | 6 | 1110 | E | 0111 | 7 | 1111 | F |================================= Logo: [cols="^2,^2,^2,^3", frame="none"] |============== | 0110~2~ = 6~16~ | 1010~2~ = A~16~ | 1101~2~ = D~16~ | 11010101101~2~ = 6AD~16~ |============== Vamos agora analisar a conversão inversa. Por exemplo: ____ A81~16~ = A . 8 . 1~16~ ____ Sabemos que: [cols="^,^,^", frame="none"] |============== | A~16~ = 1010~2~ | 8~16~ = 1000~2~ | 1~16~ = 0001~2~ |============== Portanto: ____ A81~16~ = 101010000001~2~ ____ ==== Conversão de números em uma base b qualquer para a base 10. Vamos lembrar a expressão geral já apresentada: ____ N~b~ = a~0~ × b^n^ + a~1~ × b^n-1^ + ... + a~n~ × b^0^ ____ A melhor forma de fazer a conversão é usando essa expressão. Como exemplo, o número 101101~2~ terá calculado seu valor na base 10: ____ 101101~2~ = 1×2^5^ + 0×2^4^ + 1×2^3^ + 1×2^2^ + 0×2^1^ + 1×2^0^ = 45~10~ ____ Outros exemplos: Converter A5~16~ para a base 10: ____ A5~16~ = 10×16^1^ + 5×16^0^ = 160 + 5 = 165~10~ ____ Converter 485~9~ para a base 10: ____ 485~9~ = 4×9^2^ +8×9^1^ + 5×9^0^ = 324 + 72 + 5 = 401~10~ ____ ==== Conversão de números da base 10 para uma base b qualquer A conversão de números da base 10 para uma base qualquer, emprega algoritmos que serão o inverso dos anteriores. O número decimal será dividido sucessivas vezes pela base, o resto de cada divisão ocupará sucessivamente as posições de ordem 0, 1, 2 e assim por diante, até que o resto da última divisão (que resulta em quociente 0) ocupe a posição de mais alta ordem. - Conversão do número 19~10~ para a base 2: image::images/{cap}/conversao-fazendo-divisao.eps[scaledwidth="70%", width="50%"] Logo temos: ____ 19~10~ = 10011~2~ ____ Usando a conversão anterior como prova real, temos: ____ 10011~2~ = 1×2^4^ + 0×2^3^ + 0×2^2^ + 1×2^1^ + 1×2^0^ = 19~10~ ____ Conversão do número 278~10~ para a base 16: image::images/{cap}/278_16.eps[scaledwidth="50%", width="50%"] Logo temos: ____ 278~10~ = 116~16~ ____ === Aritmética Binária Como o computador manipula os dados (números) através de uma representação binária, iremos estudar agora a aritmética do sistema binário, a mesma usada pela ULA (Unidade Lógica e Aritmética) dos processadores. [[sec_soma_binaria]] ==== Soma e Subtração Binária (((Soma binária)))(((Subtração binária))) A tabuada da soma aritmética binária: 0 + 0 = 0 0 + 1 = 1 1 + 0 = 1 1 + 1 = 0 (e “vai um” para o dígito de ordem superior) 1 + 1 + 1 = 1 (e “vai um” para o dígito de ordem superior) Por exemplo: ____ Efetuar 011100~2~ + 011010~2~ ____ NOTE: Soma-se as posições da direita para esquerda, tal como uma soma decimal. Solução: image::images/{cap}/figura1.eps[scaledwidth="40%"] A tabuada da subtração aritmética binária: 0 - 0 = 0 0 - 1 = 1 (“vem um do próximo”) 1 - 0 = 1 1 - 1 = 0 NOTE: Como é impossível tirar 1 de 0, o artifício é ``pedir emprestado'' 1 da casa de ordem superior, ou seja, na realidade o que se faz é subtrair 1~2~ de 10~2~ e encontramos 1~2~ como resultado, devendo então subtrair 1 do dígito de ordem superior. Este algoritmo é exatamente o mesmo da subtração em decimal. Por exemplo: 11100~2~ – 01010~2~ = ? Solução: image::images/{cap}/figura2.eps[scaledwidth="25%"] NOTE: Não esqueça, subtrai-se as colunas da direita para a esquerda, tal como uma subtração decimal. Você pode assistir uma aula sobre soma e subtração binária no vídeo a seguir. .Vídeo sobre Soma e Subtração Binária: http://youtu.be/NeQBC9Z5FHk ifdef::livro-pdf[] ["qrcode", size=10, scaledwidth="30%"] ------------------------- http://youtu.be/NeQBC9Z5FHk ------------------------- endif::livro-pdf[] ifdef::livro-html[] +++ +++ endif::livro-html[] ==== Multiplicação e divisão binária (((Multiplicação binária))) Vamos ver agora a tabuada da multiplicação: 0 x 0 = 0 0 x 1 = 0 1 x 0 = 0 1 x 1 = 1 NOTE: O processo de multiplicação binário é idêntico ao decimal. Exemplo: Efetuar: 101~2~ x 110~2~ Solução: image::images/{cap}/figura5.eps[scaledwidth="40%"] No entanto, a multiplicação em computadores é feita, também, por um artifício: para multiplicar A por n somamos A com A (n-1) vezes. Exemplo: ____ 4 x 3 = 4 + 4 + 4 = 12 ____ E a divisão também pode ser feita por subtrações sucessivas, até o resultado zerar ou ficar negativo. Este artifício serve apenas para divisões inteiras. Por exemplo: ____ 16 ÷ 4 -> 16 *- 4* = 12 -> 12 *- 4* = 8 -> 8 *- 4* = 4 -> 4 *– 4* = 0 ____ O número de subtrações indica o resultado da divisão inteira, neste caso, igual a 4. NOTE: Podemos concluir que qualquer operação aritmética pode ser realizada em computadores através de somas (diretas ou em complemento). Com isso diminui-se o número de circuitos lógicos de operações para o processador. [[sec_numeros_negativos]] === Números Binários Negativos (((Negativo))) Os computadores lidam com números positivos e números negativos, sendo necessário encontrar uma representação para números com sinal negativo. Existe uma grande variedade de opções, das quais nesta seção serão apresentadas apenas três para representar valores negativos: - Sinal e amplitude/magnitude (S+M) - Complemento de 1 - Complemento de 2 A representação de **Complemento de 2** é a mais utilizada, mas para compreendê-la é necessário primeiro conhecer as anteriores, que são mais simples. ==== Sinal e Amplitude/Magnitude (S + M) (((Sinal))) Como o próprio nome indica, a representação *sinal* e *amplitude* é dividida em duas partes. Utiliza um bit para representar o sinal, o bit mais à esquerda: *0* para indicar um valor positivo, *1* para indicar um valor negativo. Já o resto dos bits representam seu valor absoluto. image::images/{cap}/sinal_magnitude.eps[scaledwidth="40%", width="50%"] ==== Complemento de 1 (((Complemento de 1))) Na representação em complemento de 1 invertem-se todos os bits de um número para representar o seu complementar: assim, se converte um valor positivo para um negativo, e vice-versa. Quando o bit mais à esquerda é 0, esse valor é positivo; se for 1, então é negativo. Exemplo: ____ 01100100~2~ = 100~10~ ____ Invertendo todos os bits: ____ 10011011~2~ = –100~10~ ____ [IMPORTANT] =============== O problema desta representação é que existem 2 padrões de bits para o 0, havendo assim desperdício de representação: ____ 0~10~ = 00000000~2~ = 11111111~2~ ____ =============== ==== Complemento de 2 (((Complemento de 2))) Na representação do **complemento de 2** não há desperdiço. Para determinar o negativo de um número, inverte-se todos os seus bits e soma-se uma unidade. Exemplo: Representação binária:: 101~10~ = 01100101~2~ (com 8 bits) Invertendo todos os bits:: 10011010~2~ Somando uma unidade:: 10011011~2~ = 10011010~2~ + 1 = –101~10~ [IMPORTANT] ==== A representação em complemento para 2 tem as seguintes características: - o bit da esquerda indica o sinal; - possui processo para converter um número de positivo para negativo e de negativo para positivo; - o 0 tem uma representação única: todos os bits iguais a 0; - a gama de valores que é possível representar com n bits é -2^n-1^ ... 2^n-1^-1. ==== Exemplo: Qual o número representado por 11100100~2~ (com 8 bits)? Como o bit da esquerda é 1 este número é negativo. Invertendo todos os bits: ____ 00011011~2~ ____ Somando uma unidade: ____ 00011011~2~ + 1 = 00011100~2~ = 28~10~ ____ Logo: ____ 11100100~2~ = – 28~10~ ____ === Circuitos nos computadores para realizar as operações Na eletrônica digital de dispositivos tais como computadores, circuitos simples custam menos e operam mais rápido do que circuitos mais complexos. Logo, números em complemento de dois são usados na aritmética, pois eles permitem o uso dos circuitos mais simples, baratos e rápidos. ==== Circuito somador com complemento de 2 Uma característica do sistema de complemento de dois é que tanto os números com sinal quanto os números sem sinal podem ser somados pelo mesmo circuito. Por exemplo, suponha que você deseja somar os números sem sinal 132~10~ e 14~10~. image::images/{cap}/figura3.eps[scaledwidth="60%"] O microprocessador tem um circuito na ULA (Unidade Lógica e Aritmética) que pode somar números binários sem sinal, quando aparece o padrão 10000100~2~ em uma entrada e 00001110~2~ na outra entrada, resulta 10010010~2~ na saída. Surge a pergunta: como a ULA sabe que os padrões de bits nas entradas representam número sem sinal e não números em complemento de dois? E a resposta é: não sabe. A ULA sempre soma como se as entradas fossem números binários sem sinal. Sempre produzirá o resultado correto, mesmo se as entradas forem números em complemento de dois. image::images/{cap}/figura4.eps[scaledwidth="60%"] Isto comprova um ponto muito importante. O somador na ULA sempre soma padrões de bits como se eles fossem números binários sem sinal. É a nossa interpretação destes padrões que decide se números com ou sem sinal estão sendo tratados. O bom do complemento de dois é que os padrões de bits podem ser interpretados de qualquer maneira. Isto nos permite trabalhar com números com e sem sinal sem requerer diferentes circuitos para cada padrão. ==== Circuito subtrator com complemento de 2 A aritmética de complemento de dois também simplifica a ULA em outro ponto. Todo microprocessador precisa da instrução de subtração. Assim, a ULA deve ser capacitada a subtrair um número de outro. Entretanto, se isto necessitar de um circuito de subtração separado, a complexidade e o custo da ULA seriam aumentados. Felizmente, a aritmética de complemento de dois permite a ULA, realizar operações de subtração usando um circuito somador. Ou seja, a CPU usa o mesmo circuito tanto para soma como para subtração. Uma vez que o complemento de dois foi formado, a CPU pode realizar uma subtração indiretamente pela adição do complemento de dois do Subtraendo com Minuendo. Não esquecendo de ignorar o último transporte da adição. Como exemplo temos a subtração de 69~10~ (Minuendo) por 26~10~ (Subtraendo). Jogue fora o transporte final: image::images/{cap}/transporte-final.eps[scaledwidth="100%"] [NOTE] ==== Fica o desafio de descobrir porque o valor 74~10~ é o complemento de 10 do número 26~10~, a regra é análoga do complemento de 2 binária, ou seja, primeiro deve ser feito o complemento de 9 para cada número individualmente e depois deve ser somado o valor 1. ==== [[sec_ponto_flutuante]] === Representação de Número Fracionário no Sistema Binário ==== Notação de Ponto Fixo (((Ponto Fixo))) Esta notação conhecida como Notação de Ponto Fixo, utiliza um ponto que funciona da mesma forma que o ponto da notação decimal. Em outras palavras, os dígitos à esquerda do ponto representam a parte inteira do valor, funcionando da mesma forma que a notação binária. E os dígitos à direita do ponto representam a parte não inteira, sendo o expoente da base 2 decrementada em 1 a cada casa afastada do ponto. Exemplo: .Representação de ponto fixo image::images/{cap}/ponto-fixo.eps[] ==== Soma e subtração de números fracionários Para somarmos e subtrairmos duas representações binárias contendo ponto, basta alinharmos os pontos e aplicarmos o mesmo algoritmo de adição ou subtração binária demonstrada anteriormente. Exemplos: image::images/{cap}/figura6.eps[scaledwidth="50%"] === Fundamentos da Notação de Ponto Flutuante (((Ponto Flutuante))) A utilização da notação de ponto flutuante é muito grande em computadores, tanto para cálculos matemáticos com precisão, renderização de imagens digitais (criação de imagens pelo computador) entre outros. Os processadores atuais se dedicam muito em aperfeiçoar a técnica de seus chips para a aritmética de ponto flutuante, devido à demanda de aplicativos gráficos e jogos 3D que se utilizam muito deste recurso. Nesta subseção iremos descrever os fundamentos da aritmética de ponto flutuante, para isso, serão apresentados alguns conceitos básicos, que juntamente com os conceitos da seção anterior, servirão para o entendimento do processo desta aritmética em um sistema computacional. ==== Notação de Excesso (((Notação de Excesso))) Para trabalhar com a Notação Ponto Flutuante, precisamos entender a representação dos números inteiros (negativos e não negativos) utilizando a Notação de Excesso. Neste sistema, cada número é codificado como um padrão de bits, de comprimento convencionado. Para estabelecer um sistema de excesso, primeiro escolhemos o comprimento do padrão a ser empregado, em seguida, escrevemos todos os diferentes padrões de bits com este comprimento, na ordem em que eles seriam gerados se estivéssemos contando em binário. Logo, observamos que o primeiro desses padrões, que representa um dígito 1 como seu bit mais significativo, figura aproximadamente no centro da lista. [[tb_excesso_com_3_bits]] .Notação de excesso com 3 bits. [width="90%", frame="none", grid="all", cols="^2,^1", options="header"] |================================= | Valor Binário (Notação de Excesso)| Valor Representado | 000 | -4 | 001 | -3 | 010 | -2 | 011 | -1 | 100 (centro) | 0 | 101 | 1 | 110 | 2 | 111 | 3 |================================= Como podemos observar na <>, escolhemos este padrão para representar o ZERO, os padrões que o seguem serão utilizados para representar 1, 2, 3..., os padrões que o precedem serão adotados para a representação dos inteiros negativos -1, -2, -3... Logo na <> podemos observar o código resultante para padrões de três bits de comprimento. Exemplo: [cols="^,^", frame="none"] |============== | O valor 1 equivale a 101~2~ | O valor -1 equivale a 011~2~ |============== NOTE: No sistema de Notação de Excesso é fácil distinguir entre padrões que representam valores negativos e positivos, pois aqueles que apresentam um 0 no bit mais significativo são números negativos, servindo o mesmo como bit de sinal. ==== Notação de Ponto Flutuante O primeiro ponto a ser discutido, é o motivo da criação da Notação de Ponto Flutuante, já que na seção anterior já tínhamos trabalhado com a representação de números não inteiros utilizando a Notação de Ponto Fixo. O problema do Ponto Fixo, é que o tamanho da parte inteira e da fracionária fica fixo com relação a seu armazenamento em memória, logo para números com a parte apenas inteira, a região alocada para tratar a parte fracionária será inutilizada e vice-versa. Logo, para evitar este desperdício criou-se a Notação de Ponto Flutuante. //// TODO: Explicar melhor o desperdício da notação do ponto fixo em relação ao ponto flutuante. //// ===== Ponto Flutuante (((Ponto Flutuante))) Vamos explicar a notação de ponto flutuante por meio de um exemplo que emprega somente um byte de memória. Primeiramente, escolhemos o bit mais significativo do byte para ser o bit de sinal do número. Um ‘0’ neste bit significa que o valor representado é não negativo, enquanto o ‘1’ indica que é negativo. Em seguida dividimos os sete bits restantes em dois grupos, o campo de expoente e o campo da mantissa, como mostrado na <>. [[fig_sinal_expoente_mantissa]] .Divisão de 1 byte nos campos da Notação de Ponto Flutuante image::images/{cap}/sinal_expoente_mantissa.eps[scaledwidth="60%"] Seja um byte contendo o padrão de bits 01101011. Interpretando este padrão no formato que acabamos de definir, constatamos que o bit de sinal é ‘0’, o expoente é ‘110’, e a mantissa é ‘1011’. //// TODO: Adicionar uma imagem mostrando o número 0_110_1011 dividindo em sinal, expoente e mantissa. //// Para decodificarmos o byte, extraímos primeiro a mantissa e colocamos o ponto binário à sua esquerda, obtendo: ____ `.1011` ____ Em seguida, extraímos o conteúdo do campo do expoente e o interpretamos como um inteiro codificado em três bits pelo método de representação de excesso, nos dando o número positivo 2 (vide <>). Isto indica que devemos deslocar o ponto binário dois bits à direita (um expoente negativo codifica um deslocamento para a esquerda do ponto binário com a adição do valor 0). Como resultado temos: ____ 10.11 ____ Que representa na Notação de Ponto Fixo: ____ `=` 1×2^1^ + 0×2^0^ + 1×2^-1^ + 1×2^-2^ `=` 2+0+0,5+0,25 = 2,75 ____ Em seguida, notamos que o bit de sinal do nosso exemplo é 0, assim, o valor representado é positivo (*+2,75*). No vídeo a seguir, é possível assistir uma aula sobre a Notação de Ponto Flutuante. .Vídeo sobre o Notação de Ponto Flutuante: http://youtu.be/psyH7eBVLr4 ifdef::livro-pdf[] ["qrcode", size=10, scaledwidth="30%"] ------------------------- http://youtu.be/psyH7eBVLr4 ------------------------- endif::livro-pdf[] ifdef::livro-html[] +++ +++ endif::livro-html[] NOTE: O uso da notação de excesso para representar o expoente no sistema de Ponto Flutuante se dá pela comparação relativa das amplitudes de dois valores, consistindo apenas em emparelhar as suas representações da esquerda para a direita em busca do primeiro bit em que os dois diferem. Assim, se ambos os bits de sinal forem iguais a ‘0’, o maior dos dois valores é aquele que apresentar, da esquerda para a direita, um ‘1’ no bit em que os padrões diferem, logo ao comparar: image::images/{cap}/figura7.eps[scaledwidth="40%"] Conclui-se que o primeiro padrão é maior que o segundo, sem haver a necessidade de decodificar as representações em Ponto Flutuante, tarefa que seria mais custosa. Quando os bits de sinal forem iguais a ‘1’, o maior número é aquele que apresentar o ‘0’ na diferença dos padrões (sempre percorrendo o número da esquerda para a direita). ==== Problema com Arredondamento (((Arredondamento))) Consideremos o incômodo problema de representar o número 2,625 no sistema de ponto flutuante de um byte. Primeiramente, escrevemos 2,625 em binário, obtendo 10.101. Entretanto, ao copiarmos este código no campo da mantissa, não haverá espaço suficiente, e o último 1 (o qual representa a última parcela: 0,125) se perde, como pode ser observado na figura abaixo: [cols="^"] |============== |2,625~10~ -> 10.101~2~ |Expoente -> 110 |Mantissa -> 10101 |============== Logo temos: image::images/{cap}/bit_perdido.eps[] Ao ignorarmos este problema, e continuarmos a preencher o campo do expoente e do bit do sinal, teremos o padrão de bits 01101010, que representa o valor 2,5 e não 2,625: o fenômeno assim observado é denominado erro de arredondamento, devido o campo da mantissa ter apenas quatro bits, enquanto, por questão de precisão, seriam necessários no mínimo cinco bits. ===== Overflow e Underflow (((Overflow)))(((Underflow))) Os projetistas do hardware devem encontrar um compromisso entre a mantissa e o expoente dos números em ponto flutuante. A relação entre mantissa e expoente é expressa do seguinte modo: o aumento do número de bits reservados à mantissa aumenta a precisão do número, enquanto o aumento do número de bits reservados ao expoente aumenta o intervalo de variação dos números representados. Quando o expoente é muito grande ou muito pequeno para ser armazenado no espaço reservado para ele, ocorrem os fenômenos chamados de _overflow_ e _underflow_ respectivamente. Outro fenômeno é o próprio overflow da mantissa como mostrado acima. ==== Adição e Subtração em Ponto Flutuante A adição e a subtração de ponto flutuante tratam os expoentes junto com o valor dos operandos, logo há a necessidade de equalizar os expoentes e efetuar a operação sobre a mantissa equalizada e o resultado deve ser normalizado para a representação utilizada: Vamos analisar a seguinte adição em Ponto Flutuante: [cols="^"] |============== | 01101010 + 01011100 = ? |============== Processo: [cols="^1,^2"] |============== | Mantissa 1 = 1010 | Expoente = 110 (2 na Notação de Excesso) | Mantissa 2 = 1100 | Expoente = 101 (1 na Notação de Excesso) |============== Equalizando os expoentes, temos: image::images/{cap}/figura8.eps[] Normalizando: [cols="^"] |============== | Resultado = 1000 | Expoente = 110 (2 na Notação de Excesso) |============== Representação do resultado (01101010 + 01011100) em Ponto Flutuante = 01101000 === Lógica Binária e Portas Lógicas O <> contém a apresentação da *Lógica Binária* e a notação de *Portas Lógicas* (utilizadas nas confecções de circuitos). Lá você poderá verificar como um circuito para somar 2 bits, utilizado nos computadores, pode ser implementado através de portas lógicas. === Recapitulando Neste capítulo estudamos a origem dos sistemas de numeração. Aprendemos a trabalhar com os sistemas de numeração mais utilizados na computação. Aprendemos mais profundamente o funcionamento do sistema binário, sua aritmética, representação de números negativos e a representação de números fracionários. === Atividades 1. Efetue as conversões de base 2 para base 10: + -- a. 101~2~ {resposta} b. 10001~2~ {resposta}{solucao} c. 111010~2~ {resposta} d. 101011~2~ {resposta}{solucao} e. 101010~2~ {resposta} f. 1010111~2~ {resposta} g. 111111000111~2~ {resposta} h. 110101~2~ i. 1001~2~ [NOTE] .Resolução ==== As resoluções dos exercícios 'b' e 'd' podem ser vistas no seguinte vídeo: .Conversão de Decimal para Binário: http://youtu.be/pNSkIP3C9mA ifdef::livro-pdf[] ["qrcode", size=10, scaledwidth="20%"] ------------------------- http://youtu.be/pNSkIP3C9mA ------------------------- endif::livro-pdf[] ifdef::livro-html[] +++ +++ endif::livro-html[] ==== -- 2. Efetue as conversões de base 10 para base 2: + -- a. 13~10~ {resposta}{solucao} b. 45~10~ c. 189~10~ d. 588~10~ e. 1024~10~ {resposta}{solucao} f. 3089~10~ g. 4034~10~ h. 58~10~ {resposta}{solucao} i. 113~10~ {resposta}{solucao} [NOTE] .Resolução ==== As resoluções dos exercícios 'a' e 'e' podem ser vistas no seguinte vídeo: http://www.youtube.com/watch?v=JS8yeKtCFqQ As resoluções dos exercícios 'h' e 'i' podem ser vistas no seguinte vídeo: .Conversão de Decimal para Binário: http://youtu.be/pNSkIP3C9mA ifdef::livro-pdf[] ["qrcode", size=10, scaledwidth="20%"] ------------------------- http://youtu.be/pNSkIP3C9mA ------------------------- endif::livro-pdf[] ifdef::livro-html[] +++ +++ endif::livro-html[] ==== -- 3. Efetue as seguintes conversões: .. Converta para octal 110111011101~2~ e 1111111~2~ .. Converta para hexadecimal 101100101100~2~ .. Converta para binário FF1F~16~ e ABC~16~ 4. Efetue as seguintes conversões: .. Converta para decimal 1101.01~2~ e 10.01~2~ (Ponto Fixo) .. Converta para octal 110111011101~2~ e 1111111~2~ .. Converta para hexadecimal 101100101100~2~ .. Converta para binário 0xFF1F (Hexadecimalfootnote::[Em programação costumamos representar números hexadecimais iniciando-os com "0x", portanto 0xFF1F equivale a FF1F~16~.]) 5. Converta o número –5 para uma representação binária usando 4-bits, com as seguintes representações: .. Sinal e amplitude .. Complemento para 1 .. Complemento para 2 .. Notação de Excesso 6. Converta o número –33 para uma representação binária usando 6-bits, com as seguintes representações: .. Sinal e amplitude .. Complemento para 1 .. Complemento para 2 7. Converta para decimal o valor em binário (usando apenas 5-bits) 10101~2~, considerando as seguintes representações: .. Inteiro sem sinal .. Sinal e amplitude .. Complemento de 2 8. Efetue os seguintes cálculos usando aritmética binária de 8-bits em complemento de 2, ou seja, primeiro converta o valor para binário e depois efetue a operação aritmética. .. 4~10~ + 120~10~ .. 70~10~ + 80~10~ .. 100~10~ + (–60~10~) .. –100~10~ – 27~10~ 9. A maioria das pessoas apenas consegue contar até 10 com os seus dedos; contudo, os engenheiros informáticos podem fazer melhor! Como? Cada dedo conta como um bit, valendo 1 se esticado, e 0 se dobrado. .. Com este método, até quanto é possível contar usando ambas as mãos? .. Considere que um dos dedos na extremidade da mão é o bit do sinal numa representação em complemento para 2. Qual a gama de valores que é possível representar com ambas as mãos? 10. Efetue as operações Aritméticas no sistema binário: .. 100101010~2~ + 101010111~2~ .. 101010110~2~ – 010110111~2~ .. 100000000~2~ – 000010011~2~ .. 111111111~2~ + 101010101~2~ 11. Converta para a representação em Ponto Flutuante, com 12 bits (1: sinal; 4: expoente; 8: mantissa), os seguintes valores, dados em base 10 (apresente todos os cálculos): .. +12 .. –10.75 .. – 8.25 // Sempre manter uma linha em branco no final