Uma outra forma de explicar o “complemento 2”

Yep! Vira e mexe eu volto aos temas mais fundamentais. Eis-me aqui, de novo, falando de aritmética inteira binária pra você… Vou tentar explicar, de novo, mas de uma outra forma, o que significa usar “sinais” em valores binários inteiros e, para isso, vou recorrer à base numérica decimal. Aquela mesma a qual estamos mais que acostumados.

Números são representações simbólicas de quantidades e, portanto, não têm “sinal”. Você consegue contar 3 coisas (para citar um exemplo de quantidade), mas não consegue contar -3 coisas. O sinal ‘-‘ ai é usado para adicionar um sentido à quantidade. Pode ser que o sentido seja que “faltam” 3 coisas ou que você queira dizer 3, mas no sentido contrário ao convencional. No último caso a representação é relativa a algum ponto tomado como origem… O fato é que você adicionou o sinal ‘-‘ para colocar um sentido extra à quantidade 3. Isso significa que essa qualidade é “artificial”, em relação à quantidade de coisas… Ainda mais: significa que esse símbolo adicional complementa o significado da quantidade (lembre-se dessa palavra!).

No sistema decimal isso é fácil fazer, especialmente quando você se acostuma com o conceito de “menos” (de falta ou “sentido contrário”), mas a coisa é mais difícil quando estamos falando de representações de valores no interior de um computador… Por exemplo, poderíamos ter bits  sinalizados se usássemos 3 níveis de tensão, por exemplo, +5 V, 0 e -5V. A tensão mais alta corresponderia a ‘1’ e a mais baixa a ‘-1’, mas, neste caso, deixaríamos de ter uma base binária para trabalharmos com um sistema ternário porque 3 níveis em cada “algarismo” caracteriza um sistema de base 3… Existe também um outro problema em usar a simbologia do ‘+’ ou ‘-‘: No sistema decimal podemos escrever a quantidade do tamanho que quisermos, se tivermos paciência e tempo, e só colocarmos o sinal ‘-‘ na frente para “inverter o sentido” do valor. Num computador, a quantidade de bits disponíveis para operações aritméticas é limitado. Então, em binário, em termos de circuitos eletrônicos, não dá para usar 3 níveis e também não dá para representar um valor indefinidamente. Um bit não pode ser “negativo” (em oposição a um “positivo”) e não podemos ter tantos bits quanto quisermos. É nesse sentido que sempre digo que não existem valores inteiros negativos em binário.

Acontece que precisamos, em certos casos, representar valores binários como se fossem negativos. Ao invés de usarmos um símbolo especial como ‘-‘ para isso usamos um bit extra… Por exemplo, com um único bit podemos representar apenas dois valores: 0 e 1. Mas, se usarmos 2 bits e fizermos de conta que o bit de mais alta ordem nos diz se o valor é positivo ou negativo, então temos a nossa representação sinalizada de um valor… Por convenção, se esse bit extra for 0, o outro bit representa um valor positivo (0b01 representa o valor +1), mas se esse bit extra for 1, então o outro bit representa um valor negativo (0b11 representa -1). É como se o último bit fosse + ou -. Mas há um problema ai…

E se tivermos uma quantidade maior de bits? O que significa 0b1111 (para citar um exemplo com apenas 4 bits) em termos de valor sinalizado? Se usarmos a definição simples de que o bit de alta ordem significa ‘-‘ e os demais bits nos dão o valor, esse exemplo deveria representar -7. Mas ele, de fato, representa -1. O bit de alta ordem complementa o significado do valor adicionando -2^N ao valor dos bits inferiores (no caso N=3, que corresponde à posição do bit “de sinal”, no valor). Ou seja, 0b1111 é convertido para decimal realizando a operação -2^3+(2^2+2^1+2^0)=-8+7=-1. Note que, no caso de usarmos 2 bits apenas, o complemento é -2. Então 0b11 é calculado como -2+1=-1… Se o bit de alta ordem for zero, o complemento simplesmente não é adicionado ao valor. Repare que, -2 é o valor 2 com a complementação ‘-‘ na frente, em decimal. Acredito que daí aparece o termo “complemento 2”.

Outra explicação interessante é o do porquê do “macete” de inverter os bits e somar 1 se o último bit estiver setado, para obtermos a representação do valor como se fosse negativo. Note que, com dois bits, temos o conjunto de valores binários B={0b00, 0b01, 0b10, 0b11} que pode ser dividido em dois subconjuntos (P=\{0b00,0b01\} e M=\{0b10,0b11\}, onde B=P\cup M (dei o nome dos subconjuntos de P e M para significarem Plus e Minus, o conjunto B é dos Bits). O conjunto B é assimétrico no que se refere aos valores extremos! Do lado positivo temos, em decimal, 0 e +1, e do lado negativo, -1 e -2. Isso quer dizer que o valor -2 não pode ser “espelhado” para obtermos a representação “positiva” +2, usando apenas dois bits. Quer dizer mais ainda: temos 1 quantidade a mais do lado negativo. Assim, para obtermos -1 à partir de 1, já que temos uma quantidade extra do lado negativo, temos que “somar um” à inversão dos bits (“menos” 0b01 é o seu inverso, 0b10,  “mais 1”). No sentido contrário teremos que “tirar” esse um que colocamos, “somando” +1 ao valor negativo (x-(-1)=x+1)… Essa é a origem do “macete”.