1. Introdução

Já vimos que, na representação de números binários, a posição em que um dígito 0 ou 1 está determina o valor daquele dígito. Para relembrar, retorne ao capítulo de Sistemas de Numeração, seção 1.4. Mas, até o momento, vimos apenas a representação de números positivos. Como representar, então, números negativos? Há algumas maneiras de fazer isso.

1.1. Bit do sinal

Uma das formas é usar o primeiro bit, o mais significativo (à esquerda), para representar o sinal. Quando este bit é 0, o número é positivo e, quando é 1, negativo. É importante sempre prestar atenção na quantidade de bits usada para representar o valor.

Representamos o valor decimal 5 em binário com 8 bits da seguinte forma.

00000101

Utilizando o primeiro bit para representar o sinal, temos então a seguinte representação para o valor -5.

10000101

Se estivéssemos usando 4 bits para representar o número, por exemplo, então teríamos 5 representado como 0101 e -5 como 1101.

Vamor escrever toda a faixa de valores representáveis com 4 bits, incluindo números negativos.

-7: 1111
-6: 1110
-5: 1101
-4: 1100
-3: 1011
-2: 1010
-1: 1001
-0: 1000
 0: 0000
 1: 0001
 2: 0010
 3: 0011
 4: 0100
 5: 0101
 6: 0110
 7: 0111

Uma coisa estranha nessa representação é a presença de dois zeros: o zero negativo (1000) e o positivo (0000). Outra coisa estranha é quando tentamos somar valores positivos e negativos representados desta forma.

Ao somar 5 e -5, esperaríamos obter zero.

     0101 (5)
   + 1101 (-5)
   ------
    10010

Mas obtemos um número de 5 bits, apesar de estarmos trabalhando com 4 bits. Então ignoramos o primeiro 1, ficando somente com 0010, que equivale a 2. Se você tentar somar outro valor positivo com um negativo, também não vai funcionar nesse sistema.

Então vamos ver outra forma de representação, chamada Complemento de 1, que resolve em partes os problemas dessa representação do sinal em 1 bit.

1.2. Complemento de 1

Na representação em complemento de 1, os números positivos continuam iguais, mas os bits dos valores negativos são trocados. Assim, enquanto 5 é 0101, -5 é 1010.

-7: 1000
-6: 1001
-5: 1010
-4: 1011
-3: 1100
-2: 1101
-1: 1110
-0: 1111
 0: 0000
 1: 0001
 2: 0010
 3: 0011
 4: 0100
 5: 0101
 6: 0110
 7: 0111

Vamos somar 5 e -5 mais uma vez e verificar o resultado.

     0101 (5)
   + 1010 (-5)
   ------
     1111 (-0)

Dessa forma, obtemos zero negativo (1111), que é mais próximo do valor correto do que o 2 obtido na soma que fizemos com os números representados usando o bit do sinal. Mas somar outros valores também funciona?

     0111 (7)
   + 1101 (-2)
   ------
    10100

Se ignorarmos o primeiro bit, uma vez que estamos trabalhando com 4 bits e não 5 bits, temos o valor decimal 4 (0100). Mas 7 - 2 = 5 e não 4.

Vamos tentar com outro valor.

     0101 (5)
   + 1110 (-1)
   ------
    10011

Ignorando o primeiro bit, temos 5 - 1 = 3 (0011). Incorreto mais uma vez, pois o correto seria 4.

Há um padrão interessante acontecendo. Os resultados obtidos na operação de soma de um valor positivo com um negativo representados em complemento de 1 é sempre o valor correto - 1. Ou seja, para obter o valor correto, pegamos o valor obtido e somamos 1 a ele.

  • Para 7 - 2, obtemos 4. Logo, 4 + 1 = 5.
  • Para 5 - 1, obtemos 3. Logo, 3 + 1 = 4.
  • Para 5 - 5, obtemos -0. Logo, -0 + 1 = 0.

Espera, isso faz sentido? Nessa representação, sim. Veja:

     1111 (-0)
   + 0001 (1)
   ------
    10000

Obtemos 10000. Ignoramos o primeiro bit e tudo bem, agora temos 0000.

Outra forma de fazer isso é somar o último carry (que sempre vai ser 1) ao número de 4 bits obtido. Carry é o “vai 1” ou “vai 2”, etc, que temos quando estamos realizando uma soma no papel. Primeiro, somamos os números normalmente como já fizemos. Vamos testar com 5 e -1.

     0101 (5)
   + 1110 (-1)
   ------
    10011
    ^
    Último carry

O último carry (1) é somado ao resultado considerando somente os 4 bits (0011).

     0011 (3)
   + 0001 (1)
   ------
     0100

Assim, 3 + 1 = 4. Temos o resultado correto da operação 5 - 1.

Complemento de 1 parece uma boa abordagem para representar números negativos, uma vez que inverter bits em hardware é simples. Entretento, temos o problema que o valor sempre é uma unidade menor.

Vale a pena vermos uma abordagem que resolva esse problema, o Complemento de 2.

1.3. Complemento de 2

Usando complemento de 2, já nos livramos do zero negativo (e agora sobrou espaço para termos um -8, mas não para termos um 8).

-8: 1000
-7: 1001
-6: 1010
-5: 1011
-4: 1100
-3: 1101
-2: 1110
-1: 1111
 0: 0000
 1: 0001
 2: 0010
 3: 0011
 4: 0100
 5: 0101
 6: 0110
 7: 0111

Agora, se fizermos 5 + (-5), teremos:

     0101 (5)
   + 1011 (-5)
   ------
    10000

Ignoramos o primeiro bit e temos 0000, ou zero. E se fizermos 5 - 1?

     0101 (5)
   + 1111 (-1)
   ------
    10100

Mais uma vez, ignoramos o primeiro bit e temos 0100, ou 4. Mas, como obtemos o número negativo a partir do positivo? Como chegar de 6 (0110) a -6 (1010)?

É um processo de dois passos. Vamos observar esses passos com o número 6 (0110).

  1. Inverta os bits do valor: 0110 -> 1001
  2. Adicione 1 ao valor obtido: 1001 + 1 = 1010

Esse é o processo para negar um valor: transformá-lo de positivo para negativo e vice-versa.

Assim, finalmente temos uma representação que resolve o problema de todas as outras: sem zero negativo e sem precisar adicionar um ao resultado da soma de um valor negativo e um positivo.