Operações binárias
Posted in ASP.NET, ActionScript 3.0, Arduino, C++, Electronics, Flash, PHP on maio 25th, 2009 by Bruno Soares – 6 CommentsUltimamente tenho me deparado com muitos trechos de códigos que utilizam operações binárias, como chaveamento de multiplexador, extração de RGB a partir de um inteiro ou hexadecimal, bitshift para controlar LED Matrix, etc… E finalmente dei aquela estuda, agora vai ai um post sobre o que resultou o estudo.
Obs.: Os trechos de códigos deste post foram escritos em ActionScript, mas pode ser aplicado a C, C++, Java, Processing, PHP, entre outras linguagens.
• Introdução
• Bit Shift
• Operador >> (bitwise right shift)
• Operador << (bitwise left shift)
• Operações Bitwise
• Operador & (bitwise AND)
• Operador | (bitwise OR)
• Operador ^ (bitwise XOR)
• Operador ~ (bitwise NOT)
• Exemplos
• Extraindo o RGB de uma cor
• Chaveando multiplexador 4051
Introdução
Um operador binário, como o nome sugere, é um operador que trabalha com a representação binária do número, e como normalmente não sabemos a representação binária dos números de cabeça, vamos utilizar a tabela abaixo:
----------------------- | BIN | DEC | HEX | |-----------------------| | 1 | 1 | 1 | | 10 | 2 | 2 | | 11 | 3 | 3 | | 100 | 4 | 4 | | 101 | 5 | 5 | | 110 | 6 | 6 | | 111 | 7 | 7 | | 1000 | 8 | 8 | | 1001 | 9 | 9 | | 1010 | 10 | A | | 1011 | 11 | B | | 1100 | 12 | C | | 1101 | 13 | D | | 1110 | 14 | E | | 1111 | 15 | F | | 10000 | 16 | 10 | | 10001 | 17 | 11 | | 10010 | 18 | 12 | | 10011 | 19 | 13 | | 10100 | 20 | 14 | |-----------------------| | 11111111 | 255 | FF | -----------------------
A tabela lista os números de 1 à 20 e 255 em três bases diferentes:
• Binário (BIN)
• Decimal (DEC)
• Hexadecimal (HEX)
Analisando a tabela podemos concluir que 3d = 11b, 19d = 10011b (as letras d e b significam decimal e binário respectivamente). Lembrando que pode ser utilizada uma calculadora que opere em binário (como a do windows) ou uma alternativa de conversão de bases on-line como está: “Conversão de número binário”.
Então vamos deslocar, escorregar, escovar alguns bits para entender melhor.
Operador >>
Deslocamento de bits para a direita (bitwise right shift)
1 2 3 4 | trace(8 >> 1); // 4 trace(8 >> 2); // 2 trace(8 >> 3); // 1 trace(8 >> 4); // 0 |
Olhando os números na base decimal faz pouco sentido, ou talvez nenhum sentido, então passamos os números corretos para a base binária e tudo fica mais claro:
8d = 1000b (8 decimal é igual a 1000 em binário), então:
1000b >> 1 (deslocando uma casa para direita) temos o número:
100b que em decimal é 4(dê uma olhada na tabela).
Agora ficou fácil não? Vamos deslocar o número 13:
1 | trace(13 >> 1); // 6 |
13 em binário é 1101, deslocando uma casa para a direita (ou removendo 1 bit), fica 110, e 110 é igual a 6 em decimal.
Operador <<
Deslocamento de bits para a esquerda (bitwise left shift)
1 2 3 | trace(2 << 1); // 4 trace(2 << 2); // 8 trace(2 << 3); // 16 |
Agora é só seguir o mesmo raciocino já utilizando anteriormente.
Se 2 em base binária é igual a 10 e deslocarmos um bit para esquerda, vamos ganhar mais um zero, ficando com 100 que é igual a 4 em decimal.
Operador &
AND binário (bitwise AND)
O operador & compara bit a bit os números a sua direita e esquerda, por exemplo o resultado de 10 & 11 é 10:
1010 & 1011 ------ 1010
A comparação bit-a-bit somente retorna True (1) quando os bits comparados são iguais a 1, caso contrário retorna False (0). Formando assim um novo número.
Mais alguns exemplos para fortalecer:
|14 & 9|13 & 11|20 & 9|14 & 10|89 & 112|45 & 77|255 & 13|112 & 255| | | | | | | | | | | 1110 | 1101 | 10100| 1110 | 1011001| 101101| 11111111| 1110000| |& 1001 |& 1011 |& 1001|& 1010 |& 1110000|& 1001101|& 1101|& 11111111| | ---- | ---- | -----| ---- | -------| -------| --------| --------| | 1000 | 1001 | 0| 1010 | 1010000| 1101| 1101| 1110000| | 8d | 9d | 0d| 10d | 80d| 13d| 13d| 112d|
Operador |
OR binário (bitwise OR)
O operador | tem a mesma função do operador OR comum (||) só que atua bit-a-bit, assim como os outros operadores binários. Vejamos um exemplo:
1010 | 1011 ------ 1011
Se um dos bits comparados forem iguais a 1 a expressão retornará 1, caso os dois bits comparados forem iguais a 0, a expressão retorna 0. Agora vamos refazer o exemplo anterior trocando apenas o operador & (and binário) por | (or binário):
|14 | 9|13 | 11|20 | 9|14 | 10|89 | 112|45 | 77|255 | 13|112 | 255| | | | | | | | | | | 1110 | 1101 | 10100| 1110 | 1011001| 101101| 11111111| 1110000| || 1001 || 1011 || 1001|| 1010 || 1110000|| 1001101|| 1101|| 11111111| | ---- | ---- | -----| ---- | -------| -------| --------| --------| | 1111 | 1111 | 11101| 1110 | 1111001| 1101101| 11111111| 11111111| | 15d | 15d | 29d| 14d | 121d| 109d| 255d| 255d|
Operador ^
OU exclusivo (bitwise XOR)
A letra X na frente do OR significa Exclusive (Exclusive OR). Isso quer dizer que este operador faz a comparação binária de dois números e resulta os bits que são diferentes. Por exemplos, quais são os bits diferentes entre os números 10 e 11?
1010
^ 1011
------
1
Vamos novamente trocar o operador do exemplo anterior para analisar os resultados:
|14 ^ 9|13 ^ 11|20 ^ 9|14 ^ 10|89 ^ 112|45 ^ 77|255 ^ 13|112 ^ 255| | | | | | | | | | | 1110 | 1101 | 10100| 1110 | 1011001| 101101| 11111111| 1110000| |^ 1001 |^ 1011 |^ 1001|^ 1010 |^ 1110000|^ 1001101|^ 1101|^ 11111111| | ---- | ---- | -----| ---- | -------| -------| --------| --------| | 111 | 110 | 11101| 100 | 101001| 1100000| 11110010| 10001111| | 7d | 6d | 29d| 4d | 41d| 96d| 242d| 143d|
Operador ~
Negação (bitwise NOT)
O operador NOT inverte o sinal e complementa em um.
Negando o número 168 (~168) teremos -169.
Alguns exemplos:
1 2 3 4 5 6 | trace(~7); // -8 trace(~-7); // 6 trace(~14); // -15 trace(~13); // -14 trace(~255); // -256 trace(~112); // -113 |
Extraindo o RGB de uma cor
Sabendo que uma cor no formato RGB utiliza dois dígitos hexadecimais para definir quanto existe de Vermelho, Verde e Azul (respectivamente), formando cores como: Vermelho (FF0000), Cinza (C0C0C0), Laranja (FF9900), etc. Temos ai a possibilidade de gerar 16.581.375 de cores com este código, é só fazer a conta para conferir: 255 * 255 * 255 ou FF * FF * FF.
Vamos desmembrar um tom de azul (#347BB7) para saber quanto esta cor tem de Vermelho, Verde e Azul (o valor dos canais RGB).
1 2 3 4 5 6 7 8 9 10 |
Linha 5) Deslocando 16 bits para a direita temos:
1101000111101110110111 >> 16 = 110100 (DEC: 52)
Para o caso do vermelho não precisamos continuar a expressão (& 0xFF),
pois deslocando 16 bits para a direita já temos o resultado do vermelho,
mas se a cor estivesse no formato ARGB (Alpha Red Green Blue), seria necessário.
Linha 6) Deslocando 8 bits para conseguir o verde:
1101000111101110110111 >> 8 = 11010001111011 (DEC: 13435)
Só com o valor do deslocamentos não vamos conseguir a cor verde, então utilizamos o
operador & (AND) com o valor 255 (0xFF) para extrair a parte binária que nos interessa:
11010001111011 (DEC: 13435)
& 11111111 (DEC: 255, HEX: 0xFF)
--------------
01111011 (DEC: 123)
Linha 7) Para extrair o azul não precisamos deslocar bits e sim pegar os últimos 8 bits:
1101000111101110110111
& 11111111 (DEC: 255, HEX: 0xFF)
----------------------
10110111 (DEC: 183)
Agora voltando para o hexadecimal:
1 2 3 4 5 6 7 |
Linha 4) Deslocando 16 bits para a esquerda do número 52 (Vermelho):
110100 << 16 = 1101000000000000000000
Deslocando 8 bits para a esquerda do número 123 (Verde):
1111011 << 8 = 111101100000000
Efetuando o OR (|) com o resultado das duas operações ((r << 16) | (g << 8)):
1101000000000000000000 | 111101100000000 ---------------------- 1101000111101100000000
Efetuando a última operação, o OR com o Azul (183)
1101000111101100000000 | 0000000000000010110111 ---------------------- 1101000111101110110111
O resultado agora ficou claro. O número 1101000111101110110111 (binário) é igual a 3439543 (decimal) e 347BB7 (hexadecimal).
Chaveando multiplexador 4051
A tarefa de chavear um Multiplexador / Demultiplexador (MUX / DEMUX) 4051 é muito parecida com a extração dos canais RGB de uma cor. Você só precisa Ligar ou Desligar três pinos de seleção (select pins) para que o circuito interprete o valor gerado e transmita a voltagem da entrada desejada.
Existe um gif animado do RogerCom muito didático que demonstra o funcionamento do CI 4051, gif animado CI 4051 aqui.
Por exemplo, para ler a entrada 3, precisamos desligar o pino de seleção 0, ligar o 1 e o 2, formando assim o número 011 (binário) que é igual a 3 em decimal. Veja no código (Escrito em Arduino / C++):
1 2 3 4 5 6 7 8 9 10 11 12 | // Entrada desejada int count = 3; // Extração dos bits ativos byte s0 = count & 0x1; byte s1 = (count >> 1) & 0x1; byte s2 = (count >> 2) & 0x1; // Ligando ou desligando os pinos de seleção digitalWrite(2, s0); digitalWrite(3, s1); digitalWrite(4, s2); |
Conteúdo relacionado:
• Bitwise operation on Wikipedia


