[ Anterior | Índice | Seguinte ]

Signed Binary Representations Revisited

Juliana Lai Yeh Lee
Orientador: Routo Terada
Instituto de Matemática e Estatística
Universidade de São Paulo


Conceitos e tecnologias estudadas

Algoritmo - Implementação e Análise

       Para calcular as representações MOF, NAF, wMOF e wNAF de quaisquer números inteiros positivos no intervalo ]0, 1024[, foi feito um programa, cuja manipulação será explicada nesta seção.

       Primeiramente, obtenha o código fonte do programa em C que encontra-se aqui. Descompacte o arquivo no diretório de sua preferência. Entre no diretório mac499/ e siga as instruções que estão no arquivo Readme.txt para compilar e executar o programa. (Observação: as instruções para compilar e executar o programa devem ser realizadas no Linux. Para o Windows, utilize os comandos próprios do compilador utilizado)

       Ao executar o programa, será pedido para o usuário entrar com um número inteiro positivo no intervalo ]0, 1024[. Em seguida, será pedido o tamanho da janela w utilizada nos cálculos de wMOF e wNAF. Após isso, serão mostrados na tela as representações MOF, NAF, wMOF e wNAF.

       Caso queira continuar calculando as representações para outros números inteiros positivos no intervalo ]0, 1024[, repita o processo descrito no parágrafo anterior. Caso contrário, ou seja, não queira calcular essas representações para outros números, digite 0 (zero) para sair do programa.

       Abaixo estão os códigos que geram as formas MOF, NAF, wMOF e wNAF e suas respectivas análises. Como pode ser visto em [ 2 ], há outro modo de se calcular essas formas. Os algoritmos abaixo implementam a explicação dada anteriormente sobre cada representação:

MOF

/************************************ MOF *************************************/
/* Função que calcula o MOF de um string binário                              */
/* Recebe:                                                                    */
/*      - um inteiro n --> o número de iterações                              */
/*      - um vetor de inteiros b --> a representação binária do número        */
/*      - um vetor de inteiros mof, onde vai ser "devolvida" a forma MOF de d */

01 void MOF (int n, int b[], int mof[]) {
02  int i, j;

03   mof[n] = b[n - 1];
04   for (i = n - 1; i > 0; i--) mof[i] = b[i - 1] - b[i];
05   mof[0] = - b[0];

06 }/* MOF -------------------------------------------------------------------*/
   

       Nas linha 03 é atribuído o valor do bit mais a esquerda (mais significativo) como sendo o do primeiro bit da representação binária usual. Isso garante: O maior bit não nulo é 1.

       Na linha 04 é feita a subtração bit a bit das representações binárias do número nas formas d e 2d. Isso garante: Os sinais dos bits adjacentes não nulos (sem considerar os bits nulos) são opostos.

       Na linha 05 é atribuído o valor do bit mais a direita (menos significativo) como sendo o do último bit da representação binária usual, com o sinal negativo. Isso garante: O menor bit não nulo é -1.


NAF

/************************************ NAF *************************************/
/* Função que calcula o NAF de um string binário                              */
/* Recebe:                                                                    */
/*      - um inteiro n --> o número de iterações                              */
/*      - um vetor de inteiros b --> a representação binária do número        */
/*      - um vetor de inteiros naf, onde vai ser "devolvida" a forma NAF de d */

01 void NAF (int n, int b[], int naf[]) {
02   int i, j;

03   for(i = 0; i < n ; i++) naf[i] = b[i];
04   naf[n] = 0;

05   i = 0;
06   while ((i + 2) <= n) {

07     if (naf[i] == 1 && naf[i + 1] == 1) {
    
         /* transformação NAF */
08       naf[i] = -1;
09       naf[i + 1] = 0;
10       naf[i + 2] = 1;

11       i += 2;
12     }

13     else i++;
14   }

15 }/* NAF -------------------------------------------------------------------*/
   

       Nas linha 03 e 04, o algoritmo faz uma cópia da representação binária do número no vetor naf, acrescentando um zero a esquerda.

       Da linha 05 em diante, o algoritmo funciona da seguinte maneira:

              - Começando pelo bit mais a direita (menos significativo), são verificados esse bit e o próximo bit a esquerda.

              - Se ambos forem iguais a 1, esse 11 é substituído por 01 e o próximo bit a esquerda desse 11 recebe -1.

              - Caso contrário, verificam-se os próximos 2 bits a esquerda e o processo se repete.


wMOF

/*********************************** wMOF *************************************/
/* Função que calcula o wMOF de um string binário                             */
/* Recebe:                                                                    */
/*    - um inteiro n --> o número de iterações                                */
/*    - um vetor de inteiros b --> a representação binária do número          */
/*    - um vetor de inteiros wmof, onde vai ser "devolvida" a forma wMOF de d */

01 void wMOF (int n, int w, int b[], int wmof[]) {
02   int i, j, num, potencia, aux, aux1[NMAX + 1], aux2[NMAX];

03   if (w == 1) {
04     for (i = 0; i < n; i++) wmof[i] = b[i];
05     wmof[n] = 0;
06   }

07   else {

08     MOF(n, b, aux1);

09     i = n;
10     while ((i - w) > 0) {
11       num = 0;
12       potencia = pot (2, w - 1);
13       for (j = i; j > (i - w); j--) {
14         wmof[j] = 0;
15         num += aux1[j] * potencia;
16         potencia /= 2;
17       }

18       potencia = pot (2, w);
19       aux = num;
20       if (aux % 2 != 0) {
21         if (aux < pot (2 , (w - 1))) wmof[i - w + 1] = aux;
22         else wmof[i - w + 1] = aux - potencia;
23       }

24       else {
25         for(j = 0; j < w; j++) aux2[j] = 0;
26         if (aux < 0) {
27           num = converte (-aux, aux2);
28           for (j = i, num = w - 1; j > i - w; j--) wmof[j] = - aux2[num--];
29         }

30         else {
31           num = converte (aux, aux2);
32           for (j = i, num = w - 1; j > i - w; j--) wmof[j] = aux2[num--];
33         }

34       }
35     }
36   }

37 }/* wMOF-------------------------------------------------------------------*/
   

       Das linhas 03 a 06 é tratado o caso em que w = 1.

       Na linha 08, o algoritmo transforma a representação binária do número para a forma MOF. Ao fazer a função receber como argumento o número já na forma MOF ao invés de recebê-lo na representação binária usual, estaríamos economizando tempo e retiraríamos a linha 08.

       Da linha 09 em diante, o algoritmo funciona da seguinte maneira:

              - Começando pelo bit mais a esquerda (mais significativo), são selecionados w bits. Esses w bits representam algum número na representação binária (potência 2) e são transformados na representação decimal (potência 10) (linhas 10 a 17).

              - Como na forma wMOF cada dígito não nulo é ímpar e menor que 2w - 1 em valor absoluto, temos 2 casos:

                     * Caso o número obtido seja ímpar e:

                            - menor que 2w - 1 em valor absoluto, a linha 21 é executada.

                            - não seja menor que 2w - 1 em valor absoluto, a linha 22 é executada.

                     * Caso o número obtido seja par, transformamos esse número para a forma binária e :

                            - caso o número seja negativo, executamos as linhas 26 a 29.

                            - caso contrário, executamos as linhas 30 a 33.

              - Em seguida, o processo se repete.


wNAF

/*********************************** wNAF *************************************/
/* Função que calcula o wNAF de um string binário                             */
/* Recebe:                                                                    */
/*    - um inteiro n --> o número de iterações                                */
/*    - um inteiro w --> a largura da janela usada pelo wNAF                  */
/*    - um vetor de inteiros b --> a representação binária do número          */
/*    - um vetor de inteiros wnaf, onde vai ser "devolvida" a forma wNAF de d */

01 void wNAF (int n, int w, int b[], int wnaf[]) {
02   int i, j, num, potencia, aux[NMAX + 1];

03   if (w == 1) {
04     for (i = 0; i < n; i++) wnaf[i] = b[i];
05     wnaf[n] = 0;
06   }

07   else {

08     MOF(n, b, aux);

09     i = 0;
10     while ((w + i) < n) {
11       num = 0;
12       potencia = 1;
13       if (aux[i] != 0) {
14         for (j = i; j < (w + i); j++) {
15           num += aux[j] * potencia;
16           potencia *= 2;
17         }

18         potencia = pot (2, w);
19         if (num < pot (2 , (w - 1))) wnaf[i] = num;
20         else wnaf[i] = num - potencia;
21         i += w;
22       }

23       else {
24         wnaf[i] = 0;
25         i++;
26       }
27     }
28   }

29 }/* wNAF ------------------------------------------------------------------*/
   

       Das linhas 03 a 06 é tratado o caso em que w = 1.

       Na linha 08, o algoritmo transforma a representação binária usual do número para a forma MOF. Ao fazer a função receber como argumento o número já na forma MOF ao invés de recebê-lo na representação binária usual, estaríamos economizando tempo e retiraríamos a linha 08.

       Da linha 09 em diante, o algoritmo funciona da seguinte maneira:

              - Começando pelo bit mais a direita (menos significativo), é verificado se esse bit é nulo ou não. Caso o bit seja igual a 0, são executadas as linhas 23 a 26. Caso contrário, são selecionados w bits. Esses w bits representam algum número na representação binária (potência 2) e são transformados na representação decimal (potência 10) (linhas 14 a 17). Isso garante: Dentre quaisquer w dígitos consecutivos, ao menos um é não nulo.

              - Caso o número obtido não seja menor que 2w - 1 em valor absoluto, a linha 20 é executada. Caso contrário, a linha 19 é executada. Isso garante: Cada dígito não nulo é ímpar e menor que 2w -1 em valor absoluto.

              - Em seguida, o processo se repete. Assim que o algoritmo termina, o bit mais significativo não nulo é positivo.


Gráficos

       Os gráficos abaixo demonstram a quantidade de vezes em que o vetor com a representação binária inicial é modificado até se obter a forma de representação binária com sinal, de acordo com o tamanho de w :

Os números 687 e 1000 apresentam a mesma seqüência  

       Dos gráficos apresentados, podemos notar que a forma wMOF executa menos modificações no vetor do que a forma wNAF, dependendo do número a ser calculado e do tamanho da janela w.


DCC - IME - USP