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:
- Inverter todos os bits do seu número;
- 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:
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.
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:
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:
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.
Joia, obg
Muito legal, eu não sabia desta história toda, apenas havia ouvido falar no complemento de 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.
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?
Consegue dar um exemplo da sua dúvida por aqui? Assim, outras pessoas que tiverem a mesma dúvida poderão encontrar a resposta.
Explicação maravilhosa, Stephen! Conseguiu passar com muita clareza o conteúdo. Valeu demais!
Opa, muito obrigado! A ideia é exatamente esta: passar de forma clara e direta o que precisamos! Continue nos acompanhando que vem mais coisa!