DESENVOLVIMENTO
TREINAMENTO
CONSULTORIA
REFERÊNCIA
EMBARC NOTÍCIAS
blog.embarc.com.br
BUSCA NO SITE
Separador.gif
Login
 
VISUALIZAÇÃO DE POST
 
topoBlog.jpg
Aritmética de Ponto Fixo - parte I

No primeiro post sobre aritmética de ponto fixo, vamos rever como entender e realizar operações aritméticas básicas com números binários.

Sabemos que a maioria dos processadores mundo afora não tem suporte nativo para tratar números fracionários, ou seja, se precisamos utilizar um numero fracionário em nossos programas, temos de utilizar algum artifício para adaptar a nossa necessidade de números fracionários à realidade de números inteiros do processador.

Mas por que eu devo me preocupar com isso se a maioria dos compiladores aceitam que eu declare uma variavel do tipo float e realize operações com números fracionários ?

Bem, se toda as contas com números fracionário se resumem a converter uma leitura de um conversor A/D para mostrar em um display ao usuário 10 vezes por segundo, a resposta é que você provavelmente não precisa se preocupar com isso.

Os compiladores, ao perceberem o uso de floats em seu código adicionam funções automaticamente ao seu programa para que ele possa emular o uso de variáveis fracionárias. Isso faz o seu código crescer tanto em memória de programa quanto em memória de dados e uma operação de multiplicação utilizando esses números pode custar ao processador dezenas, centenas ou até milhares de ciclos.

Imagine que você precisa fazer contas com números fracionários milhares de vezes por segundo. O uso emulado de floats se torna uma opção inviável.

É aí que entra em cena o uso da aritmética de ponto fixo!

Para entendermos mais facilmente como os numeros podem ser tratados pelo processador, primeiramente vamos fazer uma breve revisão de como nós construímos os números em nosso dia a dia.

Todos sabemos como juntar os digitos 0~9 para formar números maiores que 9, formando dezenas, centenas, etc., mas fazemos isso de forma tão natural e automática que às vezes nem nos damos conta do processo por traz da formação desses números.

9876
= (9*1000) + (8 * 100) + (7*10) + (6*1)
= (9*(10^3)) + (8*(10^2)) + (7*(10^1)) + (6*(10^0))

Ou seja, a posição dos dígitos em um número define a potência de 10 pela qual ele é multiplicado. Usamos potências de 10 pois usamos o sistema decimal.

Quando aprendemos na escola como utilizar a vírgula com números para escrever números fracionários, o que geralmente não nos é ensinado é que a vírgula é apenas uma ferramenta que nos ajuda na representação de um número fracionário, ou seja, que quando escrevemos

0,5432

na verdade estamos representando o seguinte:

0 + (5*(1/10)) + (4*(1/100)) + (3*(1/1000)) + (2*(1/10000))

ou

0 + (5*(10^(-1))) + (4*(10^(-2))) + (3*(10^(-3))) + (2*(10^(-4)))

Mas o que isso tem a ver com números fracionários dentro do processador?

TUDO!

No sistema decimal utilizamos potências de 10 pois temos 10 digitos, ou seja, para representar numeros maiores que nove, precisamos utilizar as outras “casas decimais” à esquerda da vírgula e para representar numeros menores que 1, precisamos utilizar “casas decimais” à direita.

No sistema binário dos processadores, a diferênça é que só temos 2 dígitos (0 e 1) e isso implica em utilizar potências de 2.

Quanto vale o número binário 1101001?

Fácil!

1101001
= 1*(2^6) + 1*(2^5) + 0*(2^4) + 1*(2^3) + 0*(2^2) + 0*(2^1) + 1*(2^0)
= 1*64 +  1*32 + 0*16 + 1*8 + 0*4 + 0*2 + 1*1
= 64+32+8+1
= 105

MAS QUANDO VAMOS COMEÇAR A ENTENDER FRAÇÕES?

Calma! Vamos imaginar a seguinte possibilidade de um número binário com vírgula. Quanto valeria o número 1101,001?

1101,001
= 1*(2^3) + 1*(2^2) + 0*(2^1) + 1*(2^0) + 0*(2^(-1)) + 0*(2^(-2)) + 1*(2^(-3))
= 1*8 +  1*4 + 0*2 + 1*1 + 0*(0,5) + 0*(0,25) + 1*(0,0125)
= 8+4+1+0,125
= 13,125

Voltando ao caso decimal, quando vamos fazer operacoes de adição ou subtração, o procedimento é basicamente alinhar as casas decimais de mesma potência, fazer a conta como se não existisse a vírgula e colocar a vírgula no resultado.

12,34 + 567,8901

  12,34
 123,4567
-----------
 135,7867

Ainda no caso decimal, quando realizamos uma multiplicação um dos metodos é multiplicar os dois números como se a vírgula não existisse e adicionar ao final da conta o total de casas decimais dos fatores:

12,21 * 34,43

=   12,21 (2 casas decimais)
*   34,43 (2 casas decimais)

=    1221
 *   3443
---------
  4203903

os operadores tinhas 2 casas decimais cada uma, logo o resultado deve ter a soma das casas decimais dos operadores (2+2) que é igual a 4

420,3903

No caso binário as mesmas regras para a adição, a subtração e a multiplicação podem ser aplicadas.

(9,125)    (2,5)
1001,001 + 10,1

      1001,001
+       10,1
 -------------
      1011,101 (11,625)

(7,5)      (2,25)
111,1 * 10,01

     1111
*    1001
 ---------
     1111
    0000
   0000
  1111
 ---------
 10000111  -> 10000,111 (16,875)


Agora sim, já sabemos como realizar adição, subtração e multiplicação com números binários, mas e a divisão?

Bem, todos os processadores que já usei implementam adição e subtração de números, vários deles implementam a multiplicação (principalmente os que são mais voltados para processamento de sinais), e muito poucos implementam a divisão. Por isso não trataremos aqui da divisão de números binários.

Acho que já é bastante informação para um post. No próximo post discutiremos como são os formatos mais utilizados pelos engenheiros de DSP... Q15, Q30, etc.

Até lá!



3 comentário(s) | Comente

Embedded Architects Tecnologia                         | +55 (61) 3202-0409
SRT/S 701 bl. K sala 326, Ed. Embassy Tower | CEP 70324-908