Operações binárias
Autor: Bruno Soares | Publicado: 2009-06-07T22:41:00-03:00

Ultimamente 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&nbsp;&nbsp;&nbsp;• Operador >> (bitwise right shift)&nbsp;&nbsp;&nbsp;• Operador << (bitwise left shift)• Operações Bitwise&nbsp;&nbsp;&nbsp;• Operador &#038; (bitwise AND)&nbsp;&nbsp;&nbsp;• Operador | (bitwise OR)&nbsp;&nbsp;&nbsp;• Operador ^ (bitwise XOR)&nbsp;&nbsp;&nbsp;• Operador ~ (bitwise NOT)• Exemplos&nbsp;&nbsp;&nbsp;• Extraindo o RGB de uma cor&nbsp;&nbsp;&nbsp;• Chaveando multiplexador 4051&nbsp;IntroduçãoUm 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)trace(8 >> 1); // 4trace(8 >> 2); // 2trace(8 >> 3); // 1trace(8 >> 4); // 0Olhando 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:trace(13 >> 1); // 613 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)trace(2 << 1); // 4trace(2 << 2); // 8trace(2 << 3); // 16Agora é 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 &#038;AND binário (bitwise AND)O operador &#038; compara bit a bit os números a sua direita e esquerda, por exemplo o resultado de 10 &#038; 11 é 10:  1010&#038; 1011------  1010A 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 &#038;  9|13 &#038; 11|20 &#038;  9|14 &#038; 10|89 &#038;  112|45  &#038;  77|255  &#038;  13|112 &#038;  255||       |       |       |       |         |         |          |          ||  1110 |  1101 |  10100|  1110 |  1011001|   101101|  11111111|   1110000||&#038; 1001 |&#038; 1011 |&#038;  1001|&#038; 1010 |&#038; 1110000|&#038; 1001101|&#038;     1101|&#038; 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------  1011Se 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 &#038; (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------     1Vamos 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:trace(~7);   // -8trace(~-7);  // 6trace(~14);  // -15trace(~13);  // -14trace(~255); // -256trace(~112); // -113&nbsp;Extraindo o RGB de uma corSabendo 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).// DEC: 3439543// BIN: 1101000111101110110111var color:uint = 0x347BB7;var r:uint = (color >> 16) & 0xFF;var g:uint = (color >>  8) & 0xFF;var b:uint =  color        & 0xFF;trace("Red:", r, "Green:", g, "Blue:", b);// Red: 52 Green: 123 Blue: 183Linha 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 ooperador & (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:var r:uint = 52;var g:uint = 123;var b:uint = 183;var color:uint = (r << 16) | (g << 8) | b;trace(color.toString(16));// 347bb7Linha 4) Deslocando 16 bits para a esquerda do número 52 (Vermelho):  110100 << 16= 1101000000000000000000Deslocando 8 bits para a esquerda do número 123 (Verde):  1111011 << 8= 111101100000000Efetuando o OR (|) com o resultado das duas operações ((r << 16) | (g << 8)):  1101000000000000000000|        111101100000000  ----------------------  1101000111101100000000Efetuando a última operação, o OR com o Azul (183)  1101000111101100000000| 0000000000000010110111  ----------------------  1101000111101110110111O resultado agora ficou claro. O número 1101000111101110110111 (binário) é igual a 3439543 (decimal) e 347BB7 (hexadecimal).&nbsp;Chaveando multiplexador 4051A 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++):// Entrada desejadaint count = 3;// Extração dos bits ativosbyte s0 =  count       & 0x1;byte s1 = (count >> 1) & 0x1;byte s2 = (count >> 2) & 0x1;// Ligando ou desligando os pinos de seleçãodigitalWrite(2, s0);digitalWrite(3, s1);digitalWrite(4, s2);Conteúdo relacionado:• Post original: http://blog.bsoares.com.br/flash/operacoes-binarias• Bitwise operation on Wikipedia&nbsp;