Complemento de dois

Complemento de dois: funcionamento e exemplos 7

Nem sempre nós encontramos as bibliotecas dos CIs que precisamos para utilizar em um projeto, e na hora de ler o datasheet para usá-lo, podemos nos deparar com alguns formatos numéricos que não conhecemos. Um desses formatos muito utilizados é o chamado complemento de dois, que explicaremos neste artigo.

Por que precisamos de formatos numéricos?

Antes de tudo, precisamos conhecer a importância dos formatos numéricos.

Todos os números no mundo da eletrônica digital, incluindo os programas escritos para Arduino e Raspberry, ou mesmo os do seu computador, são expressos em bits, ou seja, 1 e 0. Para conseguir trabalhar com um número como conhecemos no formato decimal, o processador de seu dispositivo precisa deste número em formato binário. Porém fica uma dúvida: e os números negativos? Como representá-los sendo que sempre vemos os números binários representando número positivos? Como por exemplo, 1 0 0 12 = 2³ + 2º = 8 + 1 = 9.

Como representar números negativos?

Uma das formas de representar números negativos e positivos utilizando números binários é o chamado “complemento de dois”. A teoria por trás dele é muito simples, para obter a representação negativa de um número você deve:

  1. Inverter todos os bits do seu número;
  2. Somar 1.

E como o sistema sabe que queremos expressar um valor negativo ao invés de positivo? Simples: sempre que o número for negativo, o bit mais significativo (MSB, ou bit mais à esquerda) será 1. Caso contrário, o número é positivo.

Confuso? Vamos tomar por exemplo o número 9 em binário (1 0 0 12) e assumir que ele seja um valor expresso no formato do complemento de 2. Vejamos a seguinte imagem:

Explicando o complemento de dois

Seguindo as setas da esquerda para a direita passamos de binário para decimal: vemos que o MSB é 1, então pegamos o valor 1 0 0 12 e invertemos seus bits, obtendo 0 1 1 02. Após isso, somamos 1, tendo assim 0 1 1 12 como resultado final, que convertido para decimal, vale 7. Mas como sabemos que este número é a representação de um valor usando complemento de dois, sabemos que seu valor é negativo, portanto, -7.

E ainda dá pra fazer o caminho contrário! Se formos da direita para a esquerda temos o seguinte: temos o número -7 e queremos representá-lo em binário no formato de complemento de dois. Convertemos o número 7 em binário, obtendo 0 1 1 12 e subtraímos 1, o que nos retorna 0 1 1 02. Invertemos os bits, o que resulta em 1 0 0 12. Veja que chegamos em um número com o MSB valendo 1, o que nos sinaliza que é um número negativo.

A tabela a seguir mostra todos os valores possíveis de 4 bits representados em binário, hexadecimal, decimal e complemento de 2.

Tabela explicando o complemento de dois

Observe que utilizando o complemento de dois conseguimos representar valores menores (em módulo) do que utilizando o formato decimal apenas. Ao invés de ir de 0 a 15, só podemos ir de 0 a 7 e de -1 a -8: é por isso que a variável do tipo uint_8t (o u significa unsigned, ou “sem sinal”) assume valores de 0 a 255 e a do tipo int_8t vai de -128 a 127 (signed type, ou “tipo com sinal). E é justamente este “u” na frente que indica para o compilador do código que usaremos o formato do complemento de dois!
Uma curiosidade: este formato é utilizado por processadores para fazer subtrações! Observe o exemplo abaixo: exemplo de uso do complemento de dois

Onde mais o complemento de dois é usado?

Embora isso seja usado nos programas que você escreve para o seu Arduino e você talvez nem soubesse (agora sabe a teoria por trás das variáveis uint_ e int_) vários sensores utilizam este formato para expressar seus resultados, pois isto torna muito mais ágil a conversão e operação com os números (como por exemplo as contas que precisamos fazer para converter a temperatura de Celsius para Fahrenheit). Um exemplo é o sensor de temperatura MAX31875 da Maxim. Dando uma olhada no datasheet (página 9) dele vemos como ele representa a temperatura medida:

exemplo de uso do complemento de dois 2

Veja que o último bit (B15) do registrador de temperatura é responsável pelo sinal da temperatura. Para interpretar a temperatura, vamos por exemplo assumir que lemos o valor 1 1 1 1 0 1 0 0 0 0 1 12 (ignoramos os bits que são sempre zero) no formato normal (última linha). Temos o MSB igual a 1, portanto precisamos converter este valor negativo. Convertendo temos:

1) Inversão dos bits: 0 0 0 0 1 0 1 1 1 1 0 02

2) Soma 1:  0 0 0 0 1 0 1 1 1 1 0 12

3) Convertendo para decimal usando a Tabela 3 do datasheet: – (8 + 2 + 1 + 0,5 + 0,25 + 0,0625) = -11,8125 °C

Agora se você se deparar com algum sensor que utilize este formato e não tenha biblioteca pronta, você será capaz de ler os valores dele sem problema e exibir o valor certo no seu display, terminal ou smatphone.

Gostou de aprender sobre o complemento de dois? Deixe seu comentário logo abaixo. 

Faça seu comentário

Acesse sua conta e participe

7 Comentários

  1. Muito legal, eu não sabia desta história toda, apenas havia ouvido falar no complemento de 2.

  2. Show… na verdade não sabia desta aplicação até ler o manual do controlador de temperatura da novus n323, e foi ai que a coisa ficou séria, a ler os dados exibido na tela pelo monitor serial não consegui interpretar os valores, revendo o manual observei a seguinte frase: “Cada parâmetro da tabela
    é uma palavra (word) de 16 bits com sinal representado em complemento de 2.”…kkkkkkkk obrigado pela explicação…parabéns.

  3. Sthepen obrigado pela explicação, ainda fiquei com duvidas recebi exercício para fazer e to perdido em como chegar ao numero negativo.
    Poderia lhe pedir uma ajuda? tem algum e-mail?

    1. Consegue dar um exemplo da sua dúvida por aqui? Assim, outras pessoas que tiverem a mesma dúvida poderão encontrar a resposta.

  4. Explicação maravilhosa, Stephen! Conseguiu passar com muita clareza o conteúdo. Valeu demais!

    1. Opa, muito obrigado! A ideia é exatamente esta: passar de forma clara e direta o que precisamos! Continue nos acompanhando que vem mais coisa!