Baixe o app para aproveitar ainda mais
Prévia do material em texto
7-1 Capítulo SETE Números em Ponto Fixo e Ponto Flutuante 7.1 Números em ponto fixo Observação inicial: os termos “ponto fixo” e “ponto flutuante” são traduções diretas dos termos ingleses “fixed point” e “floating point”, que se referem ao símbolo utilizado nos países de língua inglesa para representar a vírgula decimal. As traduções corretas seriam, respectivamente, “vírgula fixa” e “vírgula flutuante”. Entretanto, devido ao fato dos termos “ponto fixo” e “ponto flutuante” já serem de uso corrente na literatura especializada nacional, eles serão empregados aqui também . Todos os números tratados até agora foram números inteiros, onde uma vírgula binária não apareceu explicitamente. Entretanto, estes números podem ser interpretados como apresentando uma vírgula à direita do dígito menos significativo (a posição das unidades). Assim, por exemplo, o número binário em complemento de dois 0 1 1 0 0 1 1 1 que corresponde ao número decimal 103, pode ser interpretado como apresentando uma vírgula à extrema direita 0 1 1 0 0 1 1 1 , sem que isto altere o valor por ele representado. Tem-se então uma representação em “ponto fixo”, mas sem parte fracionária. Caso deseje-se representar frações, deve-se reservar um certo número de bits para isto. Naturalmente, a quantidade de bits utilizáveis para a parte inteira diminui correspondentemente. Por exemplo, para a mesma cadeia de bits acima, tem- se os seguintes números, conforme a posição da vírgula: 0 1 1 0 0 1 1,1 Decimal = 51,5 (1 bit para fração) 0 1 1 0 0 1,1 1 Decimal = 25,75 (2 bits para fração) 0 1 1 0 0,1 1 1 Decimal = 12,875 (3 bits para fração) 0 1 1,0 0 1 1 1 Decimal = 3,21875 (5 bits para fração) 0,1 1 0 0 1 1 1 Decimal = 0,8046875 (7 bits para fração) ,01 1 0 0 1 1 1 Decimal = 0,40234375 (8 bits para fração) Ao contrário dos exemplos acima, a vírgula não é representada explicitamente. Para uma determinada notação em ponto fixo, indica-se somente quantos bits são usados para a fração e quantos bits representam a parte inteira. Todos os números manipulados seguem então a mesma notação. Dos ‘n’ bits utilizados para representar os números, utilizam-se então ‘t’ bits (t‡ 0) para a parte inteira e ‘f’ bits (f ‡ 0) para a parte fracionária, com a restrição de que t+f=n. Observe-se ainda que: 7-2 • a quantidade total de valores representáveis permanece a mesma (2n), independente da posição da vírgula (isto é, independente dos valores de ‘t’e ‘f’). • a faixa de valores representáveis depende da posição da vírgula (e da convenção utilizada, naturalmente). De um modo geral, a faixa é dada pelas mesmas fórmulas vistas anteriormente (sinal/magnitude, complemento de dois, etc), mas todos os números são agora divididos por um fator igual a 2f. Assim, por exemplo, em complemento de dois, o maior número negativo é dado por –2n-1/2f (ou seja, –2n-f-1); o maior número positivo é calculado por (2n-1–1)/2f. • os números fracionários não são contínuos, mas sim estão separados entre si por uma diferença igual a 2-f. A tabela a seguir ilustra estas observações para números de 8 bits, representados em complemento de dois (a coluna intervalo indica a diferença entre dois números consecutivos): n t f Quant. num. Menor num. Maior num. Intervalo 8 8 0 256 -128 127 1 8 7 1 256 -64 63,5 0,5 8 6 2 256 -32 31,75 0,25 8 5 3 256 -16 15,875 0,125 8 4 4 256 -8 7,9375 0,0625 8 3 5 256 -4 3,96875 0,03125 8 2 6 256 -2 1,984375 0,015625 8 1 7 256 -1 0,9921875 0,0078125 8 0 8 256 -0,5 0,49609375 0,00390625 Tabela 7.1 - Números em ponto fixo de 8 bits 7.2 Soma e subtração em ponto fixo As operações de soma e subtração em ponto fixo se realizam exatamente da mesma maneira que para números inteiros. Naturalmente, somente podem ser somados (ou subtraídos) números que possuam a mesma posição para a vírgula. Ou seja, ‘t’ e ‘f’ devem ser iguais para todos os operandos. Entretanto, números em ponto fixo com diferentes posições para a vírgula também podem ser operados, desde que um dos números seja convertido para a representação do outro. Sejam os números ‘m1’ e ‘m2’, com comprimentos ‘t1’ e ‘f1’, e ‘t2’ e ‘f2’, respectivamente. O resultado deve ter a representação de ‘m1’, ou seja, comprimentos ‘t1’ e ‘f1’ para as partes inteira e fracionária. Se ‘t1’ > ‘t2’ (a parte inteira de m1 utiliza mais bits que a parte inteira de m2), então valem as regras: 1. A parte inteira de m2, com t2 bits, deve ser extendida para t1 bits. Os bits devem ser tais que o sinal e o valor do número sejam mantidos. Assim, por exemplo, para números inteiros positivos, t1 – t2 bits em zero são acrescentados à esquerda de m2. Para números em complemento de dois, o sinal deve ser duplicado para a esquerda por t1 – t2 bits. 2. A parte fracionária de m2 deve ser reduzida para f1 bits. Isto pode ocorrer de duas maneiras: por truncagem ou por arredondamento. Na truncagem, os f2–f1 bits a direita de m2 são simplesmente eliminados. No arredondamento, primeiro soma-se 2–(f1+1) à 7-3 m2 e depois realiza-se a truncagem. Note-se que isto equivale a somar um ‘1’ na posição f2 – f1 do número; em termos aritméticos, significa que se a fração a ser eliminada é maior ou igual a 0,5 arredonda-se para cima, senão arredonda-se para baixo. A tabela abaixo ilustra alguns exemplos de conversão. Considere-se que o número final deve ser representado com 4 bits de parte inteira e 4 bits de parte fracionária. ‘T’ representa a nova fração sob truncagem, e ‘A’ representa a nova fração sob arredondamento. Num.original Representação Parte inteira Fração (T) Fração (A) 01,101101 Int. positivo 0001 1011 1011 11,101101 Int. positivo 0011 1011 1011 010,00111 Int. positivo 0010 0011 0100 01,101101 Compl.dois 0001 1011 1011 11,101101 Compl.dois 1111 1011 1011 010,00111 Compl.dois 0010 0011 0100 Tabela 7.2 - Exemplos de redução de fração Se ‘t1’ < ‘t2’ (a parte inteira de m1 utiliza menos bits que a parte inteira de m2), então valem as regras: 1. A parte inteira de m2, com t2 bits, deve ser reduzida para t1 bits. Isto só é possível se esta parte inteira puder ser representada com somente t1 bits. Se isto não for possível, a operação não pode ser realizada, pois ocorre estouro de representação. Para esta redução valem as regras analisadas na multiplicação, quando se reduzia um número de ‘2n’ bits para ‘n’ bits. 2. A parte fracionária de m2 deve ser ampliada para f1 bits. Para isto, simplesmente acrescenta-se f1 – f2 bits em zero à direita da fração de m1. A tabela a seguir ilustra alguns exemplos de conversão. Considere-se que o número final deve ser representado com 4 bits de parte inteira e 4 bits de parte fracionária. Num.original Representação Parte inteira Fração 01101,101 Int. positivo 1101 1010 111011,01 Int. positivo Estouro 0100 01000,111 Int. positivo 1000 1110 0110110,1 Compl.dois Estouro 1000 11101,101 Compl.dois 1101 1010 0001011,1 Compl.dois Estouro 1000 Tabela 7.3 - Exemplos de redução de mantissa Observe-se que sempre é possível converter um número em ponto fixo para uma representação que tenha menos bits na parte fracionária (ou mais bits na parte inteira), enquanto que o contrário nem sempre é possível Assim, quando se deve operar dois números em ponto fixo com t1 e t2 diferentes, costuma-se normalizar os operandos para aquela representação com maior parte inteira. 7.3 Multiplicação em ponto fixo A operação de multiplicação em ponto fixo se realiza exatamente da mesma maneira que a multiplicação de números inteiros (com ou sem sinal). Deve-se somente observar a nova posição da vírgula: se os dois operandos (de ‘n’ bits cada) tiverem ‘t’ bits de parte inteira e ‘f’ bits de parte fracionária, o resultado apresentará ‘2n’ bits, com ‘2t’ bits de parte inteira e ‘2f’ bits de parte fracionária. 7-4 De um modo mais geral, se o multiplicando apresentar t1 e f1 bits para as partes inteira e fracionária, e se o multiplicador tiver t2e f2 bits, então o resultado terá t1+t2 bits na parte inteira e f1+f2 bits na parte fracionária. Como na multiplicação inteira, nunca ocorre estouro de representação se forem considerados todos os bits do resultado. Após a multiplicação, se o resultado deve ser reduzido para ‘n’ bits (t + f), isto deve ser feito em duas etapas: 1. A redução da parte inteira para ‘t’ bits. Para isto elimina-se os bits mais significativos, da mesma maneira que o realizado para a multiplicação inteira. Nesta redução pode ocorrer estouro. 2. A redução da parte fracionária para ‘f’ bits. Para isto eliminam-se os bits menos significativos, por truncagem ou por arredondamento, tal como foi explicado na soma de números em ponto fixo. 7.4 Divisão em ponto fixo A operação de divisão em ponto fixo é realizada exatamente da mesma maneira que a divisão de números inteiros, observando-se as posições das vírgulas do dividendo e do divisor. Os algoritmos de divisão inteira necessitam de ‘2n’ bits para o dividendo e ‘n’ bits para o divisor. Se o divisor tem ‘t’ bits inteiros e ‘f’ bits de fração, então o dividendo deve apresentar ‘2t’ bits na parte inteira e ‘2f’ bits na parte fracionária. 1. Para estender a parte inteira, duplicam-se os bits mais significativos de acordo com a representação (zeros para números positivos, ou com o bit de sinal para números em complemento de 2). 2. Para estender a parte fracionária, basta acrescentar zeros à direita. Desta maneira obtém-se, após a execução da divisão, um quociente em ‘n’ bits (t+f) e um resto, também em ‘n’ bits (mas com ‘2f’ bits de parte fracionária!). 7.5 Números em ponto flutuante A faixa de números que podem ser representados em ponto fixo é insuficiente para a maioria das aplicações científicas, onde existe a necessidade de representar-se números muito grandes e/ou números muito pequenos. Para contornar este problema, desenvolveu-se a notação científica, onde um quintilhão é representado por 1,0 x 1018, em vez de escrevê-lo por extenso (1 000 000 000 000 000 000). A representação de números em ponto flutuante é basicamente a versão binária da notação científica. A cada número em ponto flutuante estão associados na realidade três outros números: a mantissa ‘m’, o expoente ‘e’ e a base ‘b’. No caso dos computadores atuais, a base utilizada é a binária, ou seja, b=2. O número em ponto flutuante é então calculado por: N = m x be Como a base é uma constante para um determinado sistema, o número em ponto flutuante é então representado por um par (m,e), onde ‘m’ é uma fração ou um inteiro, e ‘e’ é o exponte (sempre um inteiro). Note-se que ambos, mantissa e expoente, podem ser positivos ou negativos. A precisão de um número em ponto flutuante é determinada primariamente pelo número de bits utilizados pela mantissa. A faixa de representação R depende do número de bits do expoente. Apesar dos números em ponto flutuante representarem números reais, a faixa R não é contínua. Somente uma quantidade limitada de números (2n, onde n é a quantidade 7-5 total de bits da mantissa e do expoente) pode ser representada. Os números estão então dispersos dentro desta faixa. Os números em ponto flutuante são inerentemente redundantes, no sentido que um mesmo número pode ser representado de mais de uma maneira. Por exemplo, um quintilhão pode ser representado por 1,0.1018, ou 0,1.1019, ou mesmo 100.1016. Assim, é desejável que exista uma forma normalizada de representar um número. Para tanto, utiliza-se somente “mantissas normalizadas”. Uma mantissa está normalizada quando é constituída somente de uma parte fracionária (não existe parte inteira) e quando o primeiro dígito a direita da vírgula é diferente de zero. Assim, a forma normalizada de representar um quintilhão é dada por 0,1.1019. Na base binária, a normalização da mantissa exige que os seus dois bits mais significativos sejam diferentes. Assim, para números positivos a mantissa inicia sempre por 0,12. Para números em complemento de dois, isto implica em que o dígito mais significativo da mantissa e o bit de sinal sejam diferentes - para números positivos a mantissa inicia então por 0,12 e para números negativos a mantissa inicia por 1,02. Assim, a normalização restringe a magnitude |M| de uma mantissa ao intervalo 1/2 £ |M| < 1 Um número não normalizado é normalizado facilmente, através de deslocamentos da mantissa para a direita ou esquerda e incrementos ou decrementos do expoente, respectivamente. Note-se que um eventual estouro de representação na mantissa é facilmente resolvido: basta deslocar a mantissa para a direita, corrigir o bit mais significativo, e somar um ao expoente. Um estouro de representação no expoente, entretanto, indica um estouro na capacidade de representação dos números em ponto flutuante. Se o expoente ultrapassou o maior expoente positivo, fala-se em “overflow”; se o expoente ultrapassou o menor negativo, fala-se então em “underflow”, e o resultado fornecido normalmente é zero. A representação do número zero apresenta algumas características peculiares, que influenciam fortemente no formato utilizado para representar números em ponto flutuante em binário. A mantissa deve ser naturalmente, igual a zero, mas o expoente pode apresentar qualquer valor, uma vez que 0.be é igual a 0 para todos os valores de ‘b’ e ‘e’. Com isto tem-se: 1. A mantissa do número zero deve apresentar todos os seus bits em zero, para facilitar o teste por zero. Note-se que isto vai contra a definição formal de uma mantissa normalizada. 2. O número zero é na realidade a menor quantidade absoluta possível de representação. Durante a realização de diversos cálculos, entretanto, arredondamentos e truncagens podem levar a resultados que sejam números bem pequenos, mas não exatamente iguais a zero. Para indicar o fato do zero estar bem próximo em magnitude destes números, o expoente escolhido para o zero deve ser o maior número negativo repre- sentável. Assim, por exemplo, se o expoente possuir ‘k’ bits e for representado em complemento de dois, o expoente utilizado para o zero deverá ser –2k-1. 3. Pelas considerações anteriores, tem-se que o zero é representado por 0.b–2k-1. Entretanto, para facilitar o teste de um número para verificar se ele é igual a zero, é desejável que o número zero seja uma sequência de bits em zero, sem nenhum bit em um. Isto está em contradição com a representação acima. Para resolver este problema, codifica-se o expoente “em excesso de 2k-1”, ou seja, um expoente em zero significa na realidade a maior magnitude negativa representável. A codificação em excesso indica que existe uma quantidade a mais somada ao expoente (no caso, 2k-1); para obter-se o valor real do expoente deve-se subtrair esta quantidade do valor armazenado no campo de expoente. Ou seja, ereal = e – 2k-1. Para um expoente de 8 bits em complemento de dois, por exemplo, tem-se então uma codificação em “excesso de 128”: o expoente –128 é representado por 0; o expoente 0 é representado por 128; e o expoente 127 (o maior possível) é dado por 255. 7-6 7.6 Formatos de números em ponto flutuante Um número em ponto flutuante, representado em binário, deve fornecer as informações relativas à mantissa (seu sinal e sua magnitude) e ao expoente (também seu sinal e sua magnitude). Diversas representações podem ser utilizadas para isto (sinal/magnitude, complemento de dois, etc). Devido a isto, existem diversos formatos adotados para representar os números em ponto flutuante. Muitos deles são específicos para uma determinada família de computadores ou para um determinado fabricante. Por exemplo, o formato da série S/360-370 da IBM segue o formato comentado abaixo: • o número utiliza 32 bits: 1 bit para o sinal da mantissa, 7 bits para o expoente e 24 bits para o valor da mantissa. • a mantissa é representada em sinal magnitude; o expoente é representado em excesso- de-64. • o bit mais significativorepresenta o sinal da mantissa; os sete bits seguintes representam o expoente; e os 24 bits menos significativos representam o valor da mantissa. • a base utilizada é a base 16 (hexadecimal). Assim, o número 0,125 x 165 tem a seguinte representação: 0 1000101 001000000000000000000000 E o número – 0,125 x 16-5 tem a representação: 1 0111011 001000000000000000000000 Note-se que, como a base é 16, a mantissa é normalizada para dígitos hexadecimais (e não para dígitos binários). O formato recomendado pela IEEE (Institute of Electrical and Electronics Engineers) é descrito a seguir (existem três formatos: simples, de 32 bits, duplo, de 64 bits e quádruplo, de 128 bits): Simples Duplo Quádruplo Campos: S = sinal 1 bit 1 bit 1 bit E = expoente 8 bits 11 bits 15 bits L = primeiro bit (não representado) (não representado) 1 bit F = fração 23 bits 52 bits 111 bits Expoente Excesso-de 127 1023 16383 Maior valor 255 2047 32767 Menor valor 0 0 0 Tabela 7.4 - Formato IEEE Nesta notação, cinco grupos diferentes de números podem ser representados: números normalizados, zero, números não-normalizados, infinito e não-números (NaN): 1. Os números normalizados utilizam um expoente que vai de 1 a 254 (ou 1 a 2046, ou 1 a 32766), o primeiro bit da mantissa (L) é sempre zero e por isto não é representado. O valor do número é calculado por (–1)s . 2E-excesso . (L.F) onde L.F representa a mantissa propriamente dita; L é o primeiro bit e F é a fração. 2. O Zero é representado por um número todo em zero (E=F=L=0); note-se que o zero neste caso pode ter sinal. 7-7 3. Números não normalizados possuem o expoente em zero (E=0) e uma fração não zero. Seu uso é restrito para representação do números que não podem ser normalizados sem causar “underflow”. 4. O Infinito é representado pelo maior valor do expoente (E=255 ou 2047 ou 32767) e por uma fração em zero (F=L=0). Note-se que o infinito pode ter sinal. 5. Não-números (Not a Number) são representados pelo maior expoente e por uma fração diferente de zero. Seu uso previsto inclui a indicação de códigos de erro, situações imprevistas, etc. O bit de sinal (S) é representado no bit mais significativo; os bits seguintes representam o expoente. Os bits menos significativos são destinados à mantissa. Note-se que o bit L não é representado (exceto na notação quádrupla). 7.7 Soma e subtração de números em ponto flutuante Números em ponto flutuante, para poderem ser somados ou subtraídos, devem apresentar o mesmo expoente. Neste caso, a soma ou subtração é realizada sobre as mantissas. O número resultado é formado com a mantissa resultado e o expoente dos operandos. Como os expoentes devem ser iguais antes de poder-se realizar a operação propriamente dita, expoentes diferentes devem ser igualados. O menor dos expoentes deve ser tornado igual ao maior, e a mantissa correspondente a este expoente deve ser convenientemente deslocada para a direita, de forma que o número representado pelo par (mantissa, expoente) não se altere. Sejam X e Y dois números em ponto flutuante; sejam Xm e Ym suas mantissas e Xe e Ye os seus expoentes. As seguintes regras valem então para a soma (ou subtração): 1. Se Xe=Ye, então X±Y=(Xm±Ym) . 2Xe 2. Se Xe<Ye, então X±Y=(Xm.2(Xe-Ye)±Ym) . 2Ye 3. Se Xe>Ye, então X±Y=(Xm±Ym.2(Ye-Xe)) . 2Xe Por exemplo, no caso 2, a mantissa Xm associada ao menor expoente Xe deve ser deslocada para a direita Ye–Xe vezes, para formar uma nova mantissa Xm.2(Xe-Ye). Esta nova mantissa, que corresponde agora a um expoente Ye, pode ser operada com Ym. Note-se que, quando a mantissa Xm é deslocada para a direita, existe uma perda de precisão nos seus bits menos significativos, que são eliminados. E se a diferença Ye-Xe for maior que o número de bits utilizados para representar a mantissa, nem é necessário realizar-se a soma (ou subtração): todos os bits significativos de Xm seriam eliminados pelo deslocamento para a direita (isto equivale a somar dois números, onde um deles é muito menor que o outro). Como os números em ponto flutuante são normalmente armazenados na forma normalizada, após a operação a mantissa resultado deve ser normalizada, através de deslocamentos para a esquerda (direita) e decrementos (incrementos) do expoente, tal como explicado na seção 5. Note-se que um eventual estouro de representação é resolvido através de um deslocamento para a direita (exceto no caso em que o expoente já é o maior possível, caso em que realmente ocorre estouro). 7.8 Multiplicação de números em ponto flutuante Números em ponto flutuante são multiplicados facilmente. Basta multiplicar as mantissas e somar os expoentes. A multiplicação segue essencialmente as mesmas regras da multiplicação inteira; inclusive a mantissa resultado tem o dobro de bits de comprimento. Ela 7-8 é entretanto facilmente reduzida para o número normal de bits, através da eliminação dos seus bits menos significativos (por truncagem ou arredondamento). X x Y = (Xm x Ym) . 2(Xe+Ye) Após a multiplicação o resultado também deve ser normalizado; durante este processo pode ocorrer estouro de representação (se ocorrer estouro na representação do expoente). 7.9 Divisão de números em ponto flutuante Números em ponto flutuante são divididos facilmente. Basta dividir as mantissas e subtrair os expoentes. A mantissa do dividendo é inicialmente expandida para o dobro do seu número de bits (pela inclusão de zeros a direita) e depois as duas mantissas são divididas pelo mesmo algoritmo utilizado para números inteiros. Note-se que agora o resto é normalmente desprezado, e as etapas que na divisão inteira corrigiam quociente e resto podem ser eliminadas. X ÷ Y = (Xm ÷ Ym) . 2(Xe–Ye) Após a divisão o resultado também deve ser normalizado; durante este processo pode ocorrer estouro de representação (se ocorrer estouro na representação do expoente).
Compartilhar